【问题标题】:Why scala fails type inference for f-bound polymorphism?为什么 scala 无法对 f 绑定多态性进行类型推断?
【发布时间】:2017-02-11 20:44:23
【问题描述】:

说明问题的简单示例:

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) : UnitA 类型没有出现在参数签名中,因此您应该手动指定它。

但后者对我来说非常模糊。我刚刚添加了始终正确的类型转换,编译器奇迹般地学会了如何推断方法类型参数。但是Zero 总是Zero 类型,为什么编译器在没有我提示的情况下无法推断?

【问题讨论】:

    标签: scala type-inference f-bounded-polymorphism


    【解决方案1】:

    案例对象Zero 的类型为Zero.type,是WTF[Zero] 的子类型。因此,当您调用 printWTF(Zero) 时,编译器会推断出 W = Zero.typeZero.type &lt;: WTF[Zero.type] 为假,因此编译失败。

    另一方面,这个更复杂的签名应该可以工作:

    def printWTF[W <: WTF[W], V <: W](w: V with WTF[W]) = println(w.get)
    

    作为一个证明,这确实可以正确推断类型:

    scala> def printWTF[W <: WTF[W], V <: W](w: V with WTF[W]): (V, W) = ???
    printWTF: [W <: WTF[W], V <: W](w: V with WTF[W])(V, W)
    
    scala> :type printWTF(Box(1))
    (Box, Box)
    
    scala> :type printWTF(Zero)
    (Zero.type, Zero)
    

    【讨论】:

    • > Case object Zero 具有类型 Zero.type 并且是 WTF[Zero] 的子类型但一般规则是您可以用任何子类替换任何类条目。第二行示例的作用完全相同。它不会改变类型签名。
    • 我认为没有人知道 Scala 中类型推断的完整规则。我所知道的是,在您的示例中,它不会重试Zero.type 的所有超级类型,并且您必须像我一样使用一些额外的参数来帮助它。如果您的意思是可以将WTF[Zero] 中的Zero 替换为Zero.type,那您就错了,因为WTF 中的W 是不变的。
    • 我并不是说Zero 内的WTF[Zero] 可以替代。但是在任何地方,如果期望 Zero 参数,它可以用 Zero.type 代替,因为允许函数调用这样做,Function[Zero, T]Function[Zero.type, T] 的子类型
    • @ayvango 编译器不会尝试任意向上转换以查看是否可以通过这种方式满足类型边界。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多