简体   繁体   中英

Scala Enumeration to HList with shapeless

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM