【问题标题】:Constructing TypeTags of higher-kinded types构造更高种类的 TypeTag
【发布时间】:2015-04-30 02:05:18
【问题描述】:

给定一个简单的参数化类型,比如class LK[A],我可以写

// or simpler def tagLK[A: TypeTag] = typeTag[LK[A]]
def tagLK[A](implicit tA: TypeTag[A]) = typeTag[LK[A]]

tagLK[Int] == typeTag[LK[Int]] // true

现在我想为class HK[F[_], A] 写一个模拟:

def tagHK[F[_], A](implicit ???) = typeTag[HK[F, A]] 
// or some other implementation?

tagHK[Option, Int] == typeTag[HK[Option, Int]]

这可能吗?我试过了

def tagHK[F[_], A](implicit tF: TypeTag[F[_]], tA: TypeTag[A]) = typeTag[HK[F, A]]

def tagHK[F[_], A](implicit tF: TypeTag[F], tA: TypeTag[A]) = typeTag[HK[F, A]]

但由于显而易见的原因,两者都不起作用(在第一种情况下,F[_] 是存在类型而不是更高的类型,在第二种情况下,TypeTag[F] 无法编译)。

我怀疑答案是“不可能”,但如果不是,我会很高兴。

编辑:我们目前使用WeakTypeTags 如下(略微简化):

trait Element[A] {
  val tag: WeakTypeTag[A]
  // other irrelevant methods
}

// e.g.
def seqElement[A: Element]: Element[Seq[A]] = new Element[Seq[A]] {
  val tag = {
    implicit val tA = implicitly[Element[A]].tag
    weakTypeTag[Seq[A]]
  }
}

trait Container[F[_]] {
  def lift[A: Element]: Element[F[A]]

  // note that the bound is always satisfied, but we pass the 
  // tag explicitly when this is used
  def tag[A: WeakTypeTag]: WeakTypeTag[F[A]]
}

val seqContainer: Container[Seq] = new Container[Seq] {
  def lift[A: Element] = seqElement[A]
}

如果我们将WeakTypeTag 替换为TypeTag,所有这些都可以正常工作。不幸的是,这不会:

class Free[F[_]: Container, A: Element]

def freeElement[F[_]: Container, A: Element] {
  val tag = {
    implicit val tA = implicitly[Element[A]].tag
    // we need to get something like TypeTag[F] here
    // which could be obtained from the implicit Container[F]
    typeTag[Free[F, A]]
  }
}

【问题讨论】:

标签: scala higher-kinded-types scala-reflect


【解决方案1】:

这是否符合您的目的?

def tagHK[F[_], A](implicit tt: TypeTag[HK[F, A]]) = tt

相对于使用隐式参数分别获取FATypeTag然后组合它们,您可以直接向编译器请求您想要的标签。这会根据需要通过您的测试用例:

tagHK[Option, Int] == typeTag[HK[Option, Int]] //true

或者,如果您有 TypeTag[A] 的实例,您可以尝试:

object HK {
    def apply[F[_]] = new HKTypeProvider[F]
    class HKTypeProvider[F[_]] {
        def get[A](tt: TypeTag[A])(implicit hktt: TypeTag[HK[F, A]]) = hktt
    }
}

允许你做:

val myTT = typeTag[Int]
HK[Option].get(myTT) == typeTag[HK[Option, Int]] //true

【讨论】:

  • 好主意,可惜没有(TypeTag[A]实际上是在运行时从数据结构中获取的,不是编译器直接插入的)。
  • @AlexeyRomanov 所以你有一个TypeTag[A] 的实例?你能告诉我们更多关于你的设置是什么样的吗?当您有 TypeTag[A] 的实例并在编译时知道 F[_] 时,我在这里添加了一个解决方案。
  • 我在问题中添加了对我们情况的描述。
猜你喜欢
  • 2015-11-05
  • 2021-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2016-10-23
  • 1970-01-01
  • 2021-10-12
相关资源
最近更新 更多