Skip to content

Instantly share code, notes, and snippets.

@travisbrown
Created October 24, 2012 11:18
Show Gist options
  • Save travisbrown/3945529 to your computer and use it in GitHub Desktop.
Save travisbrown/3945529 to your computer and use it in GitHub Desktop.
Flattening deeply nested tuples with Shapeless
import shapeless._
trait Flatten[I, O <: HList] {
def apply(i: I): O
}
trait FlattenLow {
implicit def otherFlatten[I] = new Flatten[I, I :: HNil] {
def apply(i: I) = i :: HNil
}
}
object FlattenHigh extends FlattenLow {
implicit object hnilFlatten extends Flatten[HNil, HNil] {
def apply(i: HNil) = HNil
}
implicit def hlistFlatten[H, T <: HList, HO <: HList, TO <: HList, O <: HList](implicit
hev: Flatten[H, HO],
tev: Flatten[T, TO],
pre: PrependAux[HO, TO, O]
) = new Flatten[H :: T, O] {
def apply(i: H :: T) = pre(hev(i.head), tev(i.tail))
}
implicit def tupleFlatten[P <: Product, L <: HList, O <: HList](implicit
lev: HListerAux[P, L],
fev: Flatten[L, O]
) = new Flatten[P, O] {
def apply(i: P) = fev(lev(i))
}
}
import FlattenHigh._
def flatten[I, O <: HList](i: I)(implicit fev: Flatten[I, O], tev: Tupler[O]) = fev(i).tupled
val (a, b, c, d, e) = flatten((('a', "b"), ((3, 'd), 5.0)))
// Prints the following:
// a: Char = a
// b: String = b
// c: Int = 3
// d: Symbol = 'd
// e: Double = 5.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment