Scala 枚举到 HList 与无形
Scala Enumeration to HList with shapeless
假设有一个常规的 Scala 枚举对象,例如
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
是否可以在不显式指定完整 HList 类型签名的情况下将其转换为无形 HList?我遇到了几乎是我需要的 ProductArgs,但它仍然需要将每个枚举值作为单独的参数提供。同时编译器确实知道枚举集合的类型和大小,所以它一定是可能的。
尝试
import shapeless.HList
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object Macros {
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
trait ToHList {
type T <: HList
}
def toHList(enum: Enumeration): ToHList = macro impl
def impl(c: whitebox.Context)(enum: c.Tree): c.Tree = {
import c.universe._
val enum1 = c.eval(c.Expr[Enumeration](c.untypecheck(enum)))
val valueNames = enum1.values.toList.map(_.toString)
val tpe = valueNames.foldLeft[c.Tree](tq"shapeless.HNil")(
(acc, v) => tq"shapeless.::[$enum.${TermName(v)}.type, $acc]"
)
q"new Macros.ToHList { type T = $tpe }"
}
}
import Macros._
import shapeless.ops.hlist.Reify
val tohlist = toHList(WeekDay)
Reify[tohlist.T].apply() // Sun :: Sat :: Fri :: Thu :: Wed :: Tue :: Mon :: HNil
假设有一个常规的 Scala 枚举对象,例如
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
是否可以在不显式指定完整 HList 类型签名的情况下将其转换为无形 HList?我遇到了几乎是我需要的 ProductArgs,但它仍然需要将每个枚举值作为单独的参数提供。同时编译器确实知道枚举集合的类型和大小,所以它一定是可能的。
尝试
import shapeless.HList
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object Macros {
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
trait ToHList {
type T <: HList
}
def toHList(enum: Enumeration): ToHList = macro impl
def impl(c: whitebox.Context)(enum: c.Tree): c.Tree = {
import c.universe._
val enum1 = c.eval(c.Expr[Enumeration](c.untypecheck(enum)))
val valueNames = enum1.values.toList.map(_.toString)
val tpe = valueNames.foldLeft[c.Tree](tq"shapeless.HNil")(
(acc, v) => tq"shapeless.::[$enum.${TermName(v)}.type, $acc]"
)
q"new Macros.ToHList { type T = $tpe }"
}
}
import Macros._
import shapeless.ops.hlist.Reify
val tohlist = toHList(WeekDay)
Reify[tohlist.T].apply() // Sun :: Sat :: Fri :: Thu :: Wed :: Tue :: Mon :: HNil