是否可以将TypeTag转换为Manifest?

12

我们的库使用TypeTags,但现在我们需要与另一个需要Manifests的库进行交互。有没有简单的方法可以从TypeTag创建Manifest呢?


目前为止,以下链接可能会有所帮助:http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html - eruve
2个回答

12

如果你在存在TypeTag的情况下尝试天真地召唤一个Manifest,编译器会给你一个解决方案的提示:

import reflect.runtime.universe._
import reflect.ClassTag

def test[A : TypeTag] = manifest[A]

error: to create a manifest here, it is necessary to interoperate with the type
tag `evidence$1` in scope.
however typetag -> manifest conversion requires a class tag for the corresponding
type to be present.
to proceed add a class tag to the type `A` (e.g. by introducing a context bound)
and recompile.
   def test[A : TypeTag] = manifest[A]
                                   ^

因此,如果您在作用域中具有ClassTag,编译器将能够创建必要的Manifest。您有两个选项:

  • 在每个出现TypeTag的位置添加第二个上下文边界,如下所示:

    def test[A : TypeTag : ClassTag] = manifest[A] // this compiles
    
  • 或者首先将TypeTag转换为ClassTag,然后请求一个Manifest

  • def test[A](implicit ev: TypeTag[A]) = {
      // typeTag to classTag
      implicit val cl = ClassTag[A]( ev.mirror.runtimeClass( ev.tpe ) )
    
      // with an implicit classTag in scope, you can get a manifest
      manifest[A]
    }
    

4

gourlaysama的答案中使用了Class[_],因此类型参数被擦除。我想到了一种保留类型参数的实现方式,在这里:如何在TypeTag转换为Manifest期间保留类型参数?

以下是代码:

  def toManifest[T:TypeTag]: Manifest[T] = {
    val t = typeTag[T]
    val mirror = t.mirror
    def toManifestRec(t: Type): Manifest[_] = {
      val clazz = ClassTag[T](mirror.runtimeClass(t)).runtimeClass
      if (t.typeArgs.length == 1) {
        val arg = toManifestRec(t.typeArgs.head)
        ManifestFactory.classType(clazz, arg)
      } else if (t.typeArgs.length > 1) {
        val args = t.typeArgs.map(x => toManifestRec(x))
        ManifestFactory.classType(clazz, args.head, args.tail: _*)
      } else {
        ManifestFactory.classType(clazz)
      }
    }
    toManifestRec(t.tpe).asInstanceOf[Manifest[T]]
  }

这个解决方案无法很好地处理依赖类型。 - tribbloid
1
这里是 toManifest 的改进版本:https://stackoverflow.com/a/59673693/5249621 - Dmytro Mitin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接