2

考虑以下类:

class Type { def +(other:Type):Type = this}
class SubType extends Type

现在我想创建一个包装器对象,它接受一个二进制函数Type或其派生类型,让我们从:

case class Fct(f:(Type,Type) => Type)

Fct我可以使用apply 方法实例化该类_+_,但我无法使用Subtype该类传递函数,这是预期的:

val f1 = Fct(_+_) // OK
val f2 = Fct((x:SubType,y:Type) => y) // error: found: (SubType, Type) => Type, required: (Type, Type) => Type

现在我们可以定义Fct使用泛型和类型边界来接受子类型:

case class Fct[T <: Type, U <: Type, V <: Type](f:(T,U) => V)

现在f2按预期工作,但f1不再有效,我不明白为什么:

val f1 = Fct(_+_)  // error: missing parameter type
val f2 = Fct((x:SubType,y:Type) => y) // OK

是否有可以同时接受f1and的语法f2

编辑

(回复 mz)有没有办法解决工厂的差异问题?就像是:

class Fct(f:(Type,Type) => Type)
object Fct {
  def apply(f:(Type,Type) => Type): Fct = new Fct(f)
  def apply[T <: Type, U <: Type, V <: Type](f:(T,U) => V): Fct =
    new Fct((x:Type,y:Type) => {(x,y) match {
      case (a:T, b:U) => f(a,b)
      case _ => ???
    }}: Type)
}
4

1 回答 1

4

问题Fct((x: SubType, y: Type) => y)不在于语法,而在于差异。finFct有类型(Type, Type) => Type,即Function2[Type, Type, Type]Function2与其前两个类型参数是逆变的。

这意味着(SubType, Type) => Type 不是的子类型(Type, Type) => Type。因此,您不能使用它来代替(Type, Type) => Type. 请注意,Fct((x: Type, y: Type) => y)效果很好。

使用 的泛型版本Fct,当您编写时Fct(_+_),无法推断类型TU. 在这种情况下,您可以期望的最好的结果是:

Fct[SubType, Type, Type](_ + _)

简而言之,第一种方法可以正常工作,但是您的函数参数类型被确定为Type(或您可能不想要的超类型)。不过这可能没问题,因为您仍然可以将SubType参数作为参数传递给该函数,只是不能在SubType不破坏Function2. 仅当您在某处注释类型时,第二种方法才有效。

于 2015-07-23T23:08:59.993 回答