加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何测试Scala中较高类型的类型一致性

发布时间:2020-12-16 21:31:11 所属栏目:安全 来源:网络整理
导读:我试图测试两个“容器”是否使用相同的高级类型.看下面的代码: 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,_]
我试图测试两个“容器”是否使用相同的高级类型.看下面的代码:

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不是那么简单,所以即使我们不需要,我们被迫使用弱标签.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读