Last active
August 29, 2015 14:00
-
-
Save channingwalton/11138259 to your computer and use it in GitHub Desktop.
Replacing boilerplate with 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
case class Foo[T](x: T) { | |
def map[B](f: T => B) = Foo(f(x)) | |
} | |
object OldWay { | |
def combineLatest[T1, T2](e1: Foo[T1], e2: Foo[T2]): Foo[(T1, T2)] = Foo((e1.x, e2.x)) | |
def combineLatest[T1, T2, T3](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3]): Foo[(T1, T2, T3)] = | |
combineLatest(combineLatest(e1, e2), e3) map { | |
case ((v1, v2), v3) ⇒ (v1, v2, v3) | |
} | |
def combineLatest[T1, T2, T3, T4](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4]): Foo[(T1, T2, T3, T4)] = | |
combineLatest(combineLatest(e1, e2, e3), e4) map { | |
case ((v1, v2, v3), v4) ⇒ (v1, v2, v3, v4) | |
} | |
def combineLatest[T1, T2, T3, T4, T5](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5]): Foo[(T1, T2, T3, T4, T5)] = | |
combineLatest(combineLatest(e1, e2, e3, e4), e5) map { | |
case ((v1, v2, v3, v4), v5) ⇒ (v1, v2, v3, v4, v5) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6]): Foo[(T1, T2, T3, T4, T5, T6)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5), e6) map { | |
case ((v1, v2, v3, v4, v5), v6) ⇒ (v1, v2, v3, v4, v5, v6) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6, T7](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6], e7: Foo[T7]): Foo[(T1, T2, T3, T4, T5, T6, T7)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5, e6), e7) map { | |
case ((v1, v2, v3, v4, v5, v6), v7) ⇒ (v1, v2, v3, v4, v5, v6, v7) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6, T7, T8](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6], e7: Foo[T7], e8: Foo[T8]): Foo[(T1, T2, T3, T4, T5, T6, T7, T8)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5, e6, e7), e8) map { | |
case ((v1, v2, v3, v4, v5, v6, v7), v8) ⇒ (v1, v2, v3, v4, v5, v6, v7, v8) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6, T7, T8, T9](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6], e7: Foo[T7], e8: Foo[T8], e9: Foo[T9]): Foo[(T1, T2, T3, T4, T5, T6, T7, T8, T9)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5, e6, e7, e8), e9) map { | |
case ((v1, v2, v3, v4, v5, v6, v7, v8), v9) ⇒ (v1, v2, v3, v4, v5, v6, v7, v8, v9) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6], e7: Foo[T7], e8: Foo[T8], e9: Foo[T9], e10: Foo[T10]): Foo[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5, e6, e7, e8, e9), e10) map { | |
case ((v1, v2, v3, v4, v5, v6, v7, v8, v9), v10) ⇒ (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) | |
} | |
def combineLatest[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](e1: Foo[T1], e2: Foo[T2], e3: Foo[T3], e4: Foo[T4], e5: Foo[T5], e6: Foo[T6], e7: Foo[T7], e8: Foo[T8], e9: Foo[T9], e10: Foo[T10], e11: Foo[T11]): Foo[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)] = | |
combineLatest(combineLatest(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10), e11) map { | |
case ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10), v11) ⇒ (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) | |
} | |
} | |
object TheShapelessWay { | |
import shapeless._ | |
import syntax.std.tuple._ | |
import ops.hlist._ | |
object combine extends Poly { | |
implicit def caseFoo[A, B <: HList] = use((f1: Foo[A], f2: Foo[B]) => Foo(f1.x :: f2.x)) | |
} | |
def combineHLatest[L <: HList, R <: HList](l: L)(implicit r: RightFolder.Aux[L, Foo[HNil], combine.type, Foo[R]],t: Tupler[R]): Foo[Tupler[R]#Out] = | |
l.foldRight(Foo(HNil: HNil))(combine).map(_.tupled) | |
def combineToCC[L <: HList, R <: HList, T](l: L, gen: Generic[T])(implicit r: RightFolder.Aux[L, Foo[HNil], combine.type, Foo[R]], ev: R =:= gen.Repr): Foo[T] = | |
l.foldRight(Foo(HNil: HNil))(combine).map(gen.from(_)) | |
} | |
object UseIt extends App { | |
import TheShapelessWay._ | |
import shapeless.HNil | |
val r = combineHLatest(Foo("Hi") :: Foo(2) :: HNil) | |
println(r) // Foo(("Hi", 2)) | |
// now lets "blow the bloody doors off" | |
// we don't want an HList, we want some case class from the fields | |
case class Address(line1: String, country: String) | |
val genAddress = Generic[Address] | |
val addressFields = Foo("first line") :: Foo("UK") :: HNil | |
val intoAddress = combineToCC(addressFields, genAddress) | |
println(intoAddress) // Foo(Address(first line,UK)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment