3
简单的例子来说明该问题:为什么scala未能对f-绑定多态性进行类型推断?
trait WTF[W <: WTF[W]] {
def get : Int
}
trait Zero extends WTF[Zero] {
override def get : Int = 0
}
case object Zero extends Zero
final case class Box(inner : Int) extends WTF[Box] {
override def get : Int = inner
}
def printWTF[W <: WTF[W]](w : W) = println(w.get)
printWTF(Box(-1))
printWTF(Zero)
Box
是好的,但Zero
产生错误:
WTF.scala:22: error: inferred type arguments [Zero.type] do not conform to method printWTF's type parameter bounds [W <: WTF[W]]
printWTF(Zero)
^
WTF.scala:22: error: type mismatch;
found : Zero.type
required: W
printWTF(Zero)
^
two errors found
如果我手动注释的类型,它编译:
printWTF[Zero](Zero)
printWTF(Zero : Zero)
第一线路按预期工作。我经常遇到无法从参数中推断出类型参数的情况。例如def test[A](x : Int) : Unit
。 A
类型在参数签名中无处显示,因此应该手动指定它。
但是后者对我来说很模糊。我只是添加了总是为真的类型转换,奇迹般地编译器学习如何推断方法类型参数。但Zero
始终是Zero
类型,为什么编译器无法从我的提示中推断出它?
>案例对象零的类型为Zero.type和是WTF的子类型[0] 但是一般规则是你可以用任何子类替换任何类入口。第二行示例完全一样。它不会更改类型签名。 – ayvango
我不认为任何人都知道Scala中完整的类型推断规则。我所知道的是,它不会在您的示例中重试所有超类型的'Zero.type',并且您必须像我一样使用一些额外的参数来帮助它。如果你的意思是你可以用'Zero.type'替换'WTF [Zero]中的'Zero',那么你错了,因为'WTF'中的'W'是不变的。 –
我并不是说'WTF [Zero]里面的'Zero'可以替代。但任何地方,凡是预期的'Zero'参数都可以用'Zero.type'替代,因为函数调用允许这样做,'Function [Zero,T]'是Function [Zero.type,T]的子类型' – ayvango