试图了解“类型”在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
?
答案 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。