Why does the following type equivalence hold
trait Foo { type T }
val fa = new Foo { type T = Int }
implicitly[fa.T =:= Int] // OK
but when type member T
is assigned via method parameter A
then type equivalence does not hold
def makeFoo[A]: Foo = new Foo { type T = A }
val fb = makeFoo[Int]
implicitly[fb.T =:= Int] // ERROR
Intuitively I would expect if T = A
and A = Int
then T = Int
?
This is because the return type of makeFoo
is only Foo
and not Foo { type T = A }
. If you don't explicitly declare it or if you refine it, the error will go away.
def makeFoo[A] = new Foo { type T = A }
val fb = makeFoo[Int]
implicitly[fb.T =:= Int] // No more error
or
def makeFoo2[A]: Foo { type T = A } = new Foo { type T = A }
val fc: Foo { type T = Int } = makeFoo[Int]
implicitly[fc.T =:= Int] // No more error
<script src="https://scastie.scala-lang.org/knIfPcXqSQKXXCXJ2teHkg.js"></script>