[英]Scala reflection: TypeTag from context bound doesn't match type parameter
Let's start with an example code: 让我们从一个示例代码开始:
import scala.reflect.runtime.universe._
class A[T] {
}
def foo[T: TypeTag](a: A[T]) {
println(typeTag[T])
}
val a = new A[Int]
val b: A[_] = a
foo(a)
foo(b)
The output is: 输出为:
TypeTag[Int]
TypeTag[_$1]
Well, I have no clue whatsoever what is TypeTag[_$1]
, but it sure looks fancy. 好吧,我不知道什么是TypeTag[_$1]
,但是看起来确实TypeTag[_$1]
。 :) Still, I would think foo's expectations of the world are being violated here, as in if foo gets called with an instance of A[Int]
then it is guaranteed to have the typetag for Int, and not some other obscure typetag. :)仍然,我认为foo对世界的期望在这里违反了,就像foo被A[Int]
的实例调用一样,那么可以保证它具有Int的类型标签,而不是其他一些晦涩的类型标签。 Also, shouldn't typetags be "concrete" in contrast to weektypetags? 此外,与Weektypetags相比,Typetags是否应该“具体”?
Now of course I see that the compiler cannot tell in the second foo call the type parameter of A. So my expectation wasn't that I magically get typeTag[Int]
as the output of the second call, but rather I was hoping for a compile time error. 现在,我当然知道编译器无法在第二个foo调用中告诉A的类型参数。因此,我的期望不是我神奇地将typeTag[Int]
作为第二个调用的输出,但是我希望编译时错误。
Where is my missunderstanding? 我的误会在哪里?
Some futile speculation One could argue that what's going on is a call to foo with argument type A[_]
, or, to make it more explicit, the existential type A[S] forSome { type S }
. 徒劳的猜测人们可能会争辩说,正在发生的事情是使用参数类型A[_]
调用foo,或者更明确地说,是存在性类型A[S] forSome { type S }
。 An then the typeTag captures the "_" somehow. 然后,typeTag以某种方式捕获“ _”。 But this doesn't really make sense, as foo expects A[T]
for some concrete T
, and the above existential type is not A[T]
for any concrete T
. 但这并没有真正的意义,因为foo对某些具体的T
期望A[T]
,而对于任何具体的T
,上述存在类型都不是A[T]
。 Or maybe a call with an argument A[Any]
? 还是带有参数A[Any]
的呼叫? But then why not TypeTag[Any]
, and even more severely, A
is not covariant, so this would also be plain wrong. 但是,为什么不选择TypeTag[Any]
,更严重A
是, A
不是协变的,所以这也是完全错误的。
Btw, I'm using scala 2.10. 顺便说一句,我正在使用scala 2.10。
Type tags are created at compile time, and values are not available at compile time. 类型标签在编译时创建,而值在编译时不可用。 Once you cast an A[Int]
to the existential type A[_]
, all information about the type parameter has been lost. 一旦将A[Int]
转换为现有类型A[_]
,有关类型参数的所有信息都将丢失。
If they were created at run-time, based on values, type erasure would make it impossible to know A
's parameter. 如果它们是在运行时根据值创建的,则类型擦除将使不可能知道A
的参数。 Even something that is known to be an A[Int]
at compile-time is at best an A[Object]
at run-time (unless A
is Array
, but let's not go there). 即使在编译时被称为A[Int]
东西最多在运行时也不过是A[Object]
(除非A
是Array
,但不要去那里)。
So your speculation is correct, for foo(b)
, the type parameter is indeed the _
from the existential A[_]
, and that anonymous type variable prints as _$1
. 所以,你的猜测是正确的,对于foo(b)
类型参数确实是_
从生存A[_]
和匿名类型变量打印为_$1
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.