较高类型的类型推断

时间:2018-10-02 06:39:13

标签: scala generics

试图了解“类型”在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]。为什么第一行编译而第二行失败?为什么只为T推断Int

1 个答案:

答案 0 :(得分:3)

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

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

Dotty。