【问题标题】:Type inference on higher-kinded types对更高种类的类型进行类型推断
【发布时间】:2018-10-06 15:42:11
【问题描述】:

试图理解“类型”在 scala 中的实际含义。 这是一个例子:

trait A[T]
trait B[T]

val typeTest = new A[Int] with B[String]

def test [F[_],T] (t:F[T],tt:T):T= tt

test(typeTest,5)   // line #1: compiles
test(typeTest,"5") // line #2: failed

typeTest 同时是 A[Int]B[String]。为什么第 1 行编译而第 2 行失败?为什么T 仅推断为Int

【问题讨论】:

    标签: scala generics


    【解决方案1】:

    编译这段代码最简单的方法是为编译器提供提示

    test[B, String](typeTest,"5")
    

    test(typeTest: B[String],"5")
    

    有趣的是,夜间构建 Dotty 反之亦然

    val typeTest = new A[Int] with B[String] {}
    test(typeTest,"5")
    

    编译但是

    test(typeTest,5)
    

    没有

    [error] found:    Int(5)
    [error] required: String
    [error] 
    [error]   test(typeTest,5)
    [error]                 ^
    [error] one error found
    

    并且应该提供一个提示

    test[A, Int](typeTest,5)
    

    为了比较Scalac编译错误是

    Error:  type mismatch;
     found   : A[Int] with B[String]
     required: A[Any]
    Note: Int <: Any (and A[Int] with B[String] <: A[Int]), but trait A is invariant in type T.
    You may wish to define T as +T instead. (SLS 4.5)
      test(typeTest,"5")
    

    当前 Scalac 和 Dotty 在此处的行为(推断类型)不同的事实意味着(根据 Scala 规范)test(typeTest,5)test(typeTest,"5") 情况之间没有很大的区别。这只是不同编译器使用的类型推断算法的不完善。

    顺便说一句,如下 Scalac 编译错误消息,帮助编译器推断正确类型的另一种选择是创建一个 trait covariant:

    trait A[+T]
    trait B[T]
    val typeTest = new A[Int] with B[String]  
    test(typeTest,5) 
    test(typeTest,"5") 
    

    对于 Scalac 和

    trait A[+T]
    trait B[+T]
    val typeTest = new A[Int] with B[String] {}
    test(typeTest,5)
    test(typeTest,"5")
    

    对于多蒂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      相关资源
      最近更新 更多