Supposing there is a regular Scala Enumeration object, something like
object WeekDay extends Enumeration {
type WeekDay = Value
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
Is it possible to transform it to shapeless HList without explicitly specifying full HList's type signature? I have come across ProductArgs which almost what I need, but it still needs to be fed each enum value as separate arguments. At the same time compiler does know the type and the size of enums collection so it must be possible.
Try
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