【问题标题】:Scala type inference breaking down in obvious setting?Scala 类型推断在明显的设置中崩溃?
【发布时间】:2019-06-18 13:29:32
【问题描述】:

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

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)
  }

}

(如果我在 convert-call 上添加明确的 [ConcreteA],它会编译)

我得到的错误是

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 类型。

【问题讨论】:

    标签: scala type-inference


    【解决方案1】:

    问题,据我所知,类型推断是使用 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 的子类型的约束,因此它通过了。
    在解决了推理之后,编译器尝试解决 implicits。在这种情况下,它需要(证明) V &lt;:&lt; T#V,在第一种情况下有效,但在第二种情况下失败。

    【讨论】:

    • 虽然这是一种有效的解决方法,但它并不能回答问题——OP 反复要求解释他们所看到的内容。
    • @TravisBrown 你是绝对正确的,我的错。我刚刚编辑了答案......但是,我并不像我想要的那样精通编译器和类型系统。我知道您肯定比我好得多,如果您能检查答案是否正确,我将不胜感激,在此先感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 2016-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多