如何测试Scala中较高类型的类型一致性
我试图测试两个“容器”是否使用相同的高级类型.看下面的代码:
import scala.reflect.runtime.universe._ class Funct[A[_],B] class Foo[A : TypeTag](x: A) { def test[B[_]](implicit wt: WeakTypeTag[B[_]]) = println(typeOf[A] <:< weakTypeOf[Funct[B,_]]) def print[B[_]](implicit wt: WeakTypeTag[B[_]]) = { println(typeOf[A]) println(weakTypeOf[B[_]]) } } val x = new Foo(new Funct[Option,Int]) x.test[Option] x.print[Option] 输出为: false Test.Funct[Option,Int] scala.Option[_] 但是,我希望一致性测试成功.我究竟做错了什么?如何测试更高级的类型? 澄清 在我的情况下,我正在测试的值(示例中的x:A)进入宏中的列表[c.Expr [Any]].所以任何依赖于静态分辨率的解决方案(如我给出的)都不会解决我的问题. 解决方法
这是在类型参数定义和其他地方使用的下划线之间的混合. TypeTag [B [_]]中的下划线表示一个存在类型,因此您得到一个不是B的标签,但是对于一个存在的包装器,这在没有手动后处理的情况下几乎没有用.
因此,需要生成B的标签的typeOf [Funct [B,_]]不能使用包装器的标签,并且不舒服.令人不安,我的意思是它拒绝在范围内拼接标签,并且出现编译错误.如果您使用weakTypeOf,那么那个将成功,但它会为无法拼接的所有东西生成存根,从而使结果无法用于子类型检查. 在这种情况下,我们确实遇到了Scala的局限,因为我们没有办法在WeakTypeTag [B]中引用原始B,因为我们在Scala中没有实体多态.希望像DOT这样的事情会给我们带来不便,但同时你也可以使用这个解决方法(这不是很漂亮,但是我还没有想到一个更简单的方法). import scala.reflect.runtime.universe._ object Test extends App { class Foo[B[_],T] // NOTE: ideally we'd be able to write this,but since it's not valid Scala // we have to work around by using an existential type // def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B,_]] def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = { val ExistentialType(_,TypeRef(pre,sym,_)) = tt.tpe // attempt #1: just compose the type manually // but what do we put there instead of question marks?! // appliedType(typeOf[Foo],List(TypeRef(pre,Nil),???)) // attempt #2: reify a template and then manually replace the stubs val template = typeOf[Foo[Hack,_]] val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol),List(sym)) println(result) } test[Option] } // has to be top-level,otherwise the substituion magic won't work class Hack[T] 一个精明的读者会注意到,我使用了WeakTypeTag在foo的签名,即使我应该能够使用TypeTag.毕竟,我们在一个选项上调用foo,这个选项是一个很好的类型,在这个意义上,它不涉及未解析的类型参数或引起TypeTags问题的本地类.不幸的是,由于https://issues.scala-lang.org/browse/SI-7686不是那么简单,所以即使我们不需要,我们被迫使用弱标签. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |