如何定义一个类型,它表示将ArgType作为参数并返回ReturnType的所有二元或一元函数?

时间:2015-10-31 13:36:32

标签: scala

我正在尝试创建一个$.fn.ensure = function(){ if (this.length) return this; } type,在概念上可以这样定义:

UnaryOrBinaryFunc

在我的代码中,我尝试将 type A = ArgType => ReturnType type B = (ArgType, ArgType) => ReturnType type UnaryOrBinaryFunc = <Some code saying that UnaryOrBinaryFunc is either a A or a B> 定义为: UnaryOrBinaryFunc 对Eclipse来说似乎是可以接受的,我遗憾地找不到任何东西 关于在互联网上使用type UnaryOrBinaryFunc = A with B关键字与with关键字相关联。

现在,如果你想了解我为什么要这样做的一些背景,我写了一些看起来像我想要在我的项目中完成的东西:

type

请注意,我使用 sealed trait Token case object AND extends Token case object NOT extends Token type ArgType type ReturnType type A = ArgType => ReturnType type B = (ArgType, ArgType) => ReturnType type UnaryOrBinaryFunc = A with B def f: A = ??? def g: B = ??? Map[TokenType, UnaryOrBinaryFunc] ( NOT -> f, AND -> g ) 来定义f和g,因为我不想打扰它们。

现在我收到以下错误,与我的项目相同:

???

我真的不知道该怎么做,任何人都知道如何定义type mismatch; found : TypeDecl.A (which expands to) TypeDecl.ArgType ⇒ TypeDecl.ReturnType required: TypeDecl.UnaryOrBinaryFunc (which expands to) TypeDecl.ArgType ⇒ TypeDecl.ReturnType with (TypeDecl.ArgType, TypeDecl.ArgType) ⇒ TypeDecl.ReturnType ,所以我不必修改UnaryOrBinaryFunc内的内容?

非常感谢。

1 个答案:

答案 0 :(得分:3)

直接回答这个问题......

在Scala中有几种方法可以定义副产品。

最简单,也许最好的只有两种类型是使用Either

type UnaryOrBinaryFunc =
  Either[(ArgType, ArgType) => ReturnType, ArgType => ReturnType]

Map[TokenType, UnaryOrBinaryFunc] (
    NOT -> Left(f),
    AND -> Right(g)
 )

您可以为Left和Right编写一些别名,以使事物更具可读性。

如果您使用的是Shapeless库,则可以使用Coproducts实现此功能,如this问题中所述:

type UnaryOrBinaryFunc =
  (ArgType, ArgType) => ReturnType :+: ArgType => ReturnType

使用普通scala,它也可以使用技巧来创建使用implicits的副产品,如图所示here

sealed trait UnaryOrBinaryFunc
object UnaryOrBinaryFunc {
  implicit object UnaryFunc extends UnaryOrBinaryFunc[ArgType => ReturnType]
  implicit object BinaryFunc extends UnaryOrBinaryFunc[(ArgType, ArgType) => ReturnType]
}

处理UnaryOrBinaryFunc的每个函数都应该使用UnaryOrBinaryFunc的隐式参数,如给出的链接所示。

......但是,我会质疑这种复杂性是否必要。要解决这个问题,我会做一个:

  • 定义您的函数以获取ListProduct s,并在运行时切换它们的长度。

    type UnaryOrBinaryFunc = Seq[ArgType] => ReturnType
    
  • 保持一元和二元函数分离,并使任何必须处理的函数通用。

    val unaryFns = Map[TokenType, UnaryFunc] (
      NOT -> f,
      ...
    )
    
    val binaryFns = Map[TokenType, BinaryFunc] (
      AND -> g,
      ...
    )
    
    def processUnaryOrBinaryFn[T](fn: T) = {
      ...
    }
    

以上哪种解决方案最合适取决于您还需要做什么: - )。