Skip to content

Instantly share code, notes, and snippets.

@noelwelsh
Created April 30, 2016 06:18
Show Gist options
  • Save noelwelsh/b9a27832a303cc8503152fe8ce311b13 to your computer and use it in GitHub Desktop.
Save noelwelsh/b9a27832a303cc8503152fe8ce311b13 to your computer and use it in GitHub Desktop.
Attempt at extracting the names of types of the leaves of an algebraic data type
package underscoreio
package enum
import shapeless._
import shapeless.labelled._
import shapeless.syntax.singleton._
// The intention of this code is to extract the names of the types at the leaves of an algebraic data type.
// E.g. for Color at the bottom of this file,
//
// val repr = LabelledGeneric[Color]
// val names = Enum.names[repr.Repr]
//
// should result in names being List("Red", "Green", "Blue") or some permutation thereof.
object Enum {
trait NameExtractor[+A] {
def extract: List[String]
}
object NameExtractor {
implicit val hnilNameExtractor: NameExtractor[HNil] =
new NameExtractor[HNil] {
def extract: List[String] = List.empty[String]
}
implicit def hconsNameExtractor[Name <: Symbol, Head, Tail <: HList](
implicit
witness: Witness.Aux[Name],
tailExtractor: NameExtractor[Tail]
): NameExtractor[KeyTag[Name, Head] :: Tail] =
new NameExtractor[KeyTag[Name, Head] :: Tail] {
def extract: List[String] = witness.value.toString :: tailExtractor.extract
}
implicit val cnilNameExtractor: NameExtractor[CNil] =
new NameExtractor[CNil] {
def extract: List[String] = List.empty[String]
}
implicit def cconsNameExtractor[Name <: Symbol, Head, Tail <: Coproduct](
implicit
witness: Witness.Aux[Name],
tailExtractor: NameExtractor[Tail]
): NameExtractor[KeyTag[Name, Head] :+: Tail] =
new NameExtractor[KeyTag[Name, Head] :+: Tail] {
def extract: List[String] = witness.value.toString :: tailExtractor.extract
}
}
def names[A](implicit extractor: NameExtractor[A]): List[String] = {
extractor.extract
}
}
sealed abstract class Color
final case object Red extends Color
final case object Green extends Color
final case object Blue extends Color
sealed abstract class Twice
final case object One extends Twice
final case object Two extends Twice
sealed abstract class Single
final case object Once extends Single
object Example {
val color = LabelledGeneric[Color]
val red = LabelledGeneric[Red.type]
val single = LabelledGeneric[Single]
//val names = Enum.names[single.Repr]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment