通过方法类型参数分配给类型成员的值打破了类型等价
Value assigned to type member via method type parameter breaks type equivalence
为什么下面的类型等价成立
trait Foo { type T }
val fa = new Foo { type T = Int }
implicitly[fa.T =:= Int] // OK
但是当通过方法参数 A
分配类型成员 T
时,类型等价性不成立
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
的 return 类型只是 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>
我将添加这种可能性,不指定精确的 return 类型,而是指定其超类型(上限)称为 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 }
为什么下面的类型等价成立
trait Foo { type T }
val fa = new Foo { type T = Int }
implicitly[fa.T =:= Int] // OK
但是当通过方法参数 A
分配类型成员 T
时,类型等价性不成立
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
的 return 类型只是 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>
我将添加这种可能性,不指定精确的 return 类型,而是指定其超类型(上限)称为 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 }