Created
December 10, 2016 15:52
-
-
Save davegurnell/cb3c7deb27b588ad004d0013da675b3c to your computer and use it in GitHub Desktop.
shapeless getters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import shapeless._ | |
| import shapeless.labelled._ | |
| final case class Employee( | |
| name : String, | |
| number : Int, | |
| manager : Boolean | |
| ) | |
| final case class IceCream( | |
| name : String, | |
| numCherries : Int, | |
| inCone : Boolean | |
| ) | |
| trait Getter[A, B] { | |
| def apply(value: A): B | |
| } | |
| trait MkGetter[A, N] { | |
| type Out | |
| def create: Getter[A, Out] | |
| } | |
| object MkGetter { | |
| type Aux[A, N, B] = MkGetter[A, N] { type Out = B } | |
| } | |
| object Main extends Demo { | |
| val employee = Employee("Bill", 1, true) | |
| val iceCream = IceCream("Cornetto", 0, true) | |
| def getter[A, B](func: A => B): Getter[A, B] = | |
| new Getter[A, B] { | |
| def apply(value: A): B = | |
| func(value) | |
| } | |
| // implicit def hnilMkGetter[N, B]: MkGetter.Aux[HNil, N, B] = | |
| // new MkGetter[HNil, N] { | |
| // type Out = B | |
| // def create: Getter[HNil, B] = | |
| // getter(hnil => ???) | |
| // } | |
| implicit def foundMkGetter[K, H, T <: HList, N]( | |
| implicit | |
| ev: K <:< N | |
| ): MkGetter.Aux[FieldType[K, H] :: T, N, H] = | |
| new MkGetter[FieldType[K, H] :: T, N] { | |
| type Out = H | |
| def create: Getter[FieldType[K, H] :: T, H] = | |
| getter { case h :: t => h } | |
| } | |
| implicit def notFoundMkGetter[K, H, T <: HList, N, B]( | |
| implicit | |
| tailMkGetter: MkGetter.Aux[T, N, B] | |
| ): MkGetter.Aux[FieldType[K, H] :: T, N, B] = { | |
| val tailGetter = tailMkGetter.create | |
| new MkGetter[FieldType[K, H] :: T, N] { | |
| type Out = B | |
| def create: Getter[FieldType[K, H] :: T, B] = | |
| getter { case h :: t => tailGetter(t) } | |
| } | |
| } | |
| implicit def genericMkGetter[A, R, N, B]( | |
| implicit | |
| gen: LabelledGeneric.Aux[A, R], | |
| mkGetter: MkGetter.Aux[R, N, B] | |
| ): MkGetter.Aux[A, N, B] = { | |
| val rGetter = mkGetter.create | |
| new MkGetter[A, N] { | |
| type Out = B | |
| def create: Getter[A, B] = | |
| getter(a => rGetter(gen.to(a))) | |
| } | |
| } | |
| def getter[A](w: Witness)( | |
| implicit | |
| mkGetter: MkGetter[A, w.T] | |
| ): Getter[A, mkGetter.Out] = | |
| mkGetter.create | |
| val g1: Getter[Employee, String] = getter[Employee]('name) | |
| val g2: Getter[Employee, Int] = getter[Employee]('number) | |
| val g3: Getter[Employee, Boolean] = getter[Employee]('manager) | |
| // val g4 = getter[Employee]('bob) | |
| println(g1(employee)) | |
| println(g2(employee)) | |
| println(g3(employee)) | |
| // println(g4(employee)) | |
| // println(employee) | |
| // println(iceCream) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment