Created
September 22, 2012 16:57
-
-
Save jkodumal/3766759 to your computer and use it in GitHub Desktop.
Type-safe transformation from nested case classes to HLists using shapeless
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
// Based on shapeless 1.2.2 | |
import shapeless._, HList._ | |
trait RecIso[T, R] { | |
def iso(t: T) : R | |
} | |
trait RecId[T] extends RecIso[T, T] { | |
def iso(t: T) : T = t | |
} | |
implicit object intRecIso extends RecId[Int] | |
implicit object stringRecIso extends RecId[String] | |
implicit object longRecIso extends RecId[Long] | |
implicit object hnilRecIso extends RecId[HNil] | |
// Recursively transform any hlist | |
implicit def hlRecIso[D, T <: HList, R, S <: HList](implicit dri: RecIso[D, R], lri : RecIso[T, S]) = new RecIso[D :: T, R :: S] { | |
def iso(a: D :: T): R :: S = dri.iso(a.head) :: lri.iso(a.tail) | |
} | |
// Recursively transform a case class with an isomorphism into an hlist | |
implicit def ccRecIso[C <: Product, L <: HList, R <: HList](implicit is: HListIso[C, L], hlri: RecIso[L, R]) = new RecIso[C, R] { | |
import HListIso._ | |
def iso(c: C) = hlri.iso(toHList(c)) | |
} | |
def makeIso[T, R](d: T)(implicit dri: RecIso[T, R]): R = dri.iso(d) | |
// A pair of arbitrary case classes, one nested | |
case class Foo(i : Int, s : String) | |
case class Bar(s : String, f: Foo) | |
// Publish their `HListIso`'s | |
implicit def fooIso = HListIso(Foo.apply _, Foo.unapply _) | |
implicit def barIso = HListIso(Bar.apply _, Bar.unapply _) | |
type FooHList = Int :: String :: HNil | |
type BarHList = String :: FooHList :: HNil | |
val foo = Foo(1, "foo") | |
val bar = Bar("bar", foo) | |
// Yields a FooHList | |
makeIso(foo) | |
// Yields a BarHList | |
makeIso[Bar, BarHList](bar) // you have to help out scala's type inference in this case |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment