从宏中的 HList 获取类型序列

Get sequence of types from HList in macro

Context:我正在尝试编写一个静态识别非固定数量类型的宏。我正在尝试使用 HList 将这些类型作为单个类型参数传递。它将被称为 m[ConcreteType1 :: ConcreteType2 :: ... :: HNil]()。然后宏构建一个匹配语句,它需要在编译时找到一些隐式,有点像 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' 的方法也很有趣 - 我希望它会更简单,但还没有完全研究。

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

目前您似乎不需要宏。似乎输入 类 或 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