Reputation: 3390
Trying to understand what "type" actually means in scala. Here is an example:
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
is A[Int]
an B[String]
at the same time. Why line #1 compiles and #2 failed? Why T
is inferred only for Int
?
Upvotes: 4
Views: 137
Reputation: 51648
The easiest way to make this code compile is to provide a hint for compiler
test[B, String](typeTest,"5")
or
test(typeTest: B[String],"5")
It's funny that with the nightly build of Dotty vice versa
val typeTest = new A[Int] with B[String] {}
test(typeTest,"5")
compiles but
test(typeTest,5)
doesn't
[error] found: Int(5)
[error] required: String
[error]
[error] test(typeTest,5)
[error] ^
[error] one error found
and one should provide a hint
test[A, Int](typeTest,5)
For comparison Scalac compile error was
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")
The fact that currently Scalac and Dotty behaves (infer types) here differently means that (according to Scala specification) there is no deep difference betweeen test(typeTest,5)
and test(typeTest,"5")
cases. It's just imperfectness of type inference algorithms used by different compilers.
By the way, as follows from Scalac compile error message, one more option to help compilers to infer correct types is to make a trait covariant:
trait A[+T]
trait B[T]
val typeTest = new A[Int] with B[String]
test(typeTest,5)
test(typeTest,"5")
for Scalac and
trait A[+T]
trait B[+T]
val typeTest = new A[Int] with B[String] {}
test(typeTest,5)
test(typeTest,"5")
for Dotty.
Upvotes: 3