为什么以下类型等效性成立
trait Foo { type T }
val fa = new Foo { type T = Int }
implicitly[fa.T =:= Int] // OK
但是当通过方法参数T
分配类型成员A
时,类型等效性不成立
def makeFoo[A]: Foo = new Foo { type T = A }
val fb = makeFoo[Int]
implicitly[fb.T =:= Int] // ERROR
直觉上我希望T = A
和A = Int
然后T = Int
?
这是因为makeFoo
的返回类型仅为Foo
,而不是Foo { type T = A }
。如果您未明确声明它或对其进行优化,则错误将消失。
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>
我将添加不指定精确返回类型,而是将其超类型(上限)称为whiteboxity的可能性。
在Scala 2中,可以通过whitebox macros实现>
import scala.language.experimental.macros import scala.reflect.macros.whitebox def makeFoo[A]: Foo = macro impl[A] def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ q"new Foo { type T = ${weakTypeOf[A]} }" } val fb = makeFoo[Int] implicitly[fb.T =:= Int] //compiles
在Dotty中,可以通过关键字
transparent
(currently)来实现
transparent inline def makeFoo[A]: Foo = new Foo { type T = A } val fb = makeFoo[Int] summon[fb.T =:= Int] //compiles
以前的语法是
inline def makeFoo[A] <: Foo = new Foo { type T = A }