Scala 类型推断在明显的设置中崩溃?

标签 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 的结果call 进入一个这样注释的 val 类型。

最佳答案

据我所知,问题在于类型推断使用 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没有任何限制,因此编译器简单绑定(bind) Vv 的类型它已经知道它是什么。然后,它检查返回类型 T它知道必须是 ConcreteA ,它满足它必须是 A 的子类型的约束,因此它通过了。
在解决了推理之后,编译器尝试解决 隐含 .在这种情况下,它需要得到(证明)V <:< T#V ,在第一种情况下有效,但在第二种情况下失败。

关于Scala 类型推断在明显的设置中崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56650328/

相关文章:

map 内的Scala Spark过滤器

haskell - 为什么需要减少上下文?

type-inference - D 中的函数和委托(delegate)文字

scala - 在 Futures 中包装 Slick 查询

scala - Scala 中的 '???' 是什么?

scala - Scala 中如何定义字段?

scala - 为什么以及什么时候 trait 和 object 应该有相同的名字?

dynamic - Dart 2中的动态类型可以分配给差异类型的多个值吗?

在 Flowable 中使用方法引用时,Kotlin 无法推断类型

haskell - 这个 Haskell 函数的类型签名是什么?