gpt4 book ai didi

scala - 使用宏构建列表时推断 HList 类型

转载 作者:行者123 更新时间:2023-12-04 13:50:09 24 4
gpt4 key购买 nike

我有一个方法取 HList并使用它来构建类的实例。
我想提供一些简化的语法,隐藏显式的缺点。所以我想从:

MyThingy.describe( 42 :: true :: "string" :: HNil)


MyThingy.describe {
42
true
"string"
}

哪里 MyThingy被定义为
class MyThingy[L <: HList](elems: L)

我已经尝试过这个宏
def describe[L <: HList](elements: Unit): MyThingy[L] = macro MyThingyMacros.describeImpl[L]


def describeImpl[L <: shapeless.HList : c.WeakTypeTag](c: Context)(elems: c.Tree): c.Tree = {
import c.universe._

def concatHList: PartialFunction[Tree, Tree] = {
case Block(l, _) =>
val els = l.reduceRight((x, y) => q"shapeless.::($x,$y)")
q"$els :: shapeless.HNil"
}

concatHList.lift(elems) match {
case None => c.abort(c.enclosingPosition, "BOOM!")
case Some(elemsHList) =>
val tpe = c.typecheck(elemsHList).tpe
q"new MyThingy[$tpe]($elemsHList)"
}

}

但是类型检查器爆炸了:

exception during macro expansion: scala.reflect.macros.TypecheckException: inferred type arguments [Int,Boolean] do not conform to method apply's type parameter bounds [H,T <: shapeless.HList]



显然编译器试图推断 [Int, Boolean]从宏扩展之前的块。我也不明白为什么它需要两个参数,其中 describeMyThing只需要一个。

有没有办法让宏产生的树驱动类型推断?

最佳答案

如果您可以使用逗号分隔的参数列表,那么您可以遵循 shapeless HList 中使用的样式。伴生对象 apply方法,

scala> import shapeless._
import shapeless._

scala> object MyThingy {
| def describe[P <: Product, L <: HList](p : P)
| (implicit gen: Generic.Aux[P, L]) : L = gen.to(p)
| }
defined object MyThingy

scala> MyThingy.describe(42, true, "String")
res0: this.Repr = 42 :: true :: String :: HNil

scala> res0.head
res1: Int = 42

一般来说,如果有可行的非宏替代方案,我的建议是避免使用宏。

关于scala - 使用宏构建列表时推断 HList 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25474325/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com