从宏列表中的HList获取类型的序列

问题描述 投票:0回答:1

Context:我正在尝试编写一个静态地知道非固定数量类型的宏。我正在尝试使用HList将这些类型作为单个类型参数传递。它将被称为m[ConcreteType1 :: ConcreteType2 :: ... :: HNil]()。然后,宏会构建一个match语句,该语句要求在编译时找到一些隐式对象,就像json序列化程序可能需要隐式编码器一样。当在固定数量的类型参数上使用宏时,我有一个有效的宏实现,如下所示:

def m[T1, T2](): Int = macro mImpl[T1, T2]

def mImpl[T1: c.WeakTypeTag, T2: c.WeakTypeTag](c: Context)(): c.Expr[Int] = {
  import c.universe._
  val t = Seq(
    weakTypeOf[T1],
    weakTypeOf[T2]
  ).map(c => cq"a: $c => externalGenericCallRequiringImplicitsAndReturningInt(a)")
  val cases = q"input match { case ..$t }"
  c.Expr[Int](cases)
}

问题:如果我的某个WeakTypeTag[T]有一个T <: HList,是否有任何方法可以将其转换为Seq[Type]

def hlistToSeq[T <: HList](hlistType: WeakTypeTag[T]): Seq[Type] = ???

我的直觉是编写一个递归匹配,将每个T <: HList转换为H :: THNil,但我认为Scala中不存在这种匹配。

[我想知道有其他方法可以将任意大小的类型的列表放入宏,请记住,我需要Seq[Type]而不是Expr[Seq[Type]],因为我需要在它们上进行映射宏代码。

用Dotty编写类似的'macro'的方法也很有趣-我希望在那里会更简单,但是还没有完全研究。

Edit(clarification):我使用宏的原因是我希望我正在编写的库的用户提供类型的集合(也许以HList的形式),库可以迭代并期望与之相关的隐式对象。我说的是库,但是它将与用途一起编译,以便运行宏。在任何情况下,它都可以与不同的类型集合一起重用。这有点令人困惑,但是我想我已经解决了这一点-我只需要能够构建可以对类型列表进行操作的宏即可。

scala shapeless scala-macros hlist
1个回答
0
投票

当前您似乎不需要宏。似乎类型类或shapeless.Poly就足够了。

def externalGenericCallRequiringImplicitsAndReturningInt[C](a: C)(implicit 
  mtc: MyTypeclass[C]): Int = mtc.anInt

trait MyTypeclass[C] {
  def anInt: Int
}
object MyTypeclass {
  implicit val mtc1: MyTypeclass[ConcreteType1] = new MyTypeclass[ConcreteType1] {
    override val anInt: Int = 1
  }

  implicit val mtc2: MyTypeclass[ConcreteType2] = new MyTypeclass[ConcreteType2] {
    override val anInt: Int = 2
  }

  //...
}

val a1: ConcreteType1 = null
val a2: ConcreteType2 = null
externalGenericCallRequiringImplicitsAndReturningInt(a1) //1
externalGenericCallRequiringImplicitsAndReturningInt(a2) //2
© www.soinside.com 2019 - 2024. All rights reserved.