[英]Get sequence of types from HList in macro
Context : I'm trying to write a macro that is statically aware of an non-fixed number of types.上下文:我正在尝试编写一个静态感知非固定数量类型的宏。 I'm trying to pass these types as a single type parameter using an HList
.我正在尝试使用HList
将这些类型作为单个类型参数HList
。 It would be called as m[ConcreteType1 :: ConcreteType2 :: ... :: HNil]()
.它将被称为m[ConcreteType1 :: ConcreteType2 :: ... :: HNil]()
。 The macro then builds a match statement which requires some implicits to be found at compile time, a bit like how a json serialiser might demand implicit encoders.宏然后构建一个 match 语句,它需要在编译时找到一些隐式,有点像 json 序列化器可能需要隐式编码器。 I've got a working implementation of the macro when used on a fixed number of type parameters, as follows:当在固定数量的类型参数上使用时,我有一个宏的工作实现,如下所示:
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)
}
Question : If I have a WeakTypeTag[T]
for some T <: HList
, is there any way to turn that into a Seq[Type]
?问题:如果我有一些T <: HList
的WeakTypeTag[T]
,有没有办法把它变成Seq[Type]
?
def hlistToSeq[T <: HList](hlistType: WeakTypeTag[T]): Seq[Type] = ???
My instinct is to write a recursive match which turns each T <: HList
into either H :: T
or HNil
, but I don't think that kind of matching exists in scala.我的本能是编写一个递归匹配,将每个T <: HList
转换为H :: T
或HNil
,但我认为 scala 中不存在这种匹配。
I'd like to hear of any other way to get a list of arbitrary size of types into a macro, bearing in mind that I would need a Seq[Type]
, not Expr[Seq[Type]]
, as I need to map over them in macro code.我想听听任何其他方式将任意大小的类型列表放入宏中,记住我需要Seq[Type]
,而不是Expr[Seq[Type]]
,因为我需要映射在宏代码中覆盖它们。
A way of writing a similar 'macro' in Dotty would be interesting too - I'm hoping it'll be simpler there, but haven't fully investigated yet.一种在 Dotty 中编写类似“宏”的方法也很有趣——我希望它会更简单,但还没有完全调查清楚。
Edit (clarification) : The reason I'm using a macro is that I want a user of the library I'm writing to provide a collection of types (perhaps in the form of an HList
), which the library can iterate over and expect implicits relating to.编辑(澄清) :我使用宏的原因是我希望我正在编写的库的用户提供类型集合(可能以HList
的形式),库可以迭代并期望隐含相关。 I say library, but it will be compiled together with the uses, in order for the macros to run;我说的是库,但它会和用途一起编译,以便宏运行; in any case it should be reusable with different collections of types.在任何情况下,它都应该可以在不同类型的集合中重用。 It's a bit confusing, but I think I've worked this bit out - I just need to be able to build macros that can operate on lists of types.这有点令人困惑,但我想我已经解决了这一点 - 我只需要能够构建可以对类型列表进行操作的宏。
Currently you seem not to need macros.目前您似乎不需要宏。 It seems type classes or shapeless.Poly
can be enough.似乎 type classes 或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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.