Scala类型推断在明显的环境中崩溃了?

时间:2019-06-18 13:29:32

标签: scala type-inference

我有一段相当简单的代码无法编译,因为显然不能推断出类型。我想了解为什么它不起作用,因为我有很多类型注释,它应该可以工作。代码是

object MyApp {

  trait A { 
    type V
    val value: V
  }

  case class ConcreteA(value: Int) extends A { type V=Int }

  def convert[T<:A](v: T#V): T = ConcreteA(v.asInstanceOf[Int]).asInstanceOf[T] // brief method with casts for illustration purposes only


  def main(args: Array[String]) {
    val i: Int = 10
    val converted: ConcreteA = convert(i)
  }

}

(如果我在[ConcreteA]调用中添加显式convert,则会进行编译)

我得到的错误是

MyApp.scala:19: error: no type parameters for method convert: (v: T#V)T exist so that it can be applied to arguments (Int)
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : Int
 required: ?T#V
    val converted: ConcreteA = convert(i)
                               ^
MyApp.scala:19: error: type mismatch;
 found   : Int
 required: T#V
    val converted: ConcreteA = convert(i)
                                       ^
MyApp.scala:19: error: type mismatch;
 found   : T
 required: MyApp.ConcreteA
    val converted: ConcreteA = convert(i)
                                      ^
three errors found

有人可以向我解释吗?

编辑:我希望Scala在这里推论TConcreteA。我这样做是因为convert调用的结果变成了这样注释的val类型。

1 个答案:

答案 0 :(得分:4)

据我所知,问题 是类型推断使用Unification algorithm来工作,该类型将试图满足给定值的约束。它将首先尝试证明输入v满足类型T#V,但是此刻,它没有关于T的任何信息,因此在检查结果类型是否正确之前就失败了满足条件。
如果您明确指定TConcreteA,那么它将可以继续。

但是,您可以通过使用Generalized Type Constraints推迟推理之后对参数的类型检查来使其工作。

def convert[T <: A, V](v: V)(implicit ev: V <:< T#V): T = ???

val converted: ConcreteA = convert(10)
// converted: ConcreteA = ConcreteA(10)

val converted: ConcreteA = convert("hey")
// Compile error:  Cannot prove that String <:< T#V.

在这种情况下,值v没有任何限制,因此编译器将V绑定到已经知道它是什么的v类型。然后,它检查它知道必须为T的返回类型ConcreteA,该返回类型满足必须为A的子类型的约束,因此它可以通过。
解决了推论后,编译器尝试解决隐式。在这种情况下,它需要获得V <:< T#V(证明),在第一种情况下有效,在第二种情况下失败。