Created
November 30, 2016 00:08
-
-
Save mandubian/7d61a9fb7c7a7d09ae43e0a8ac4c6c28 to your computer and use it in GitHub Desktop.
UbikList or abstracting heterogenous list to anykind
This file contains 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
// Basic shapeless-style HList | |
sealed trait HList | |
sealed trait HNil extends HList { | |
def ::[H](h : H) = Test.::(h, this) | |
} | |
final case object HNil extends HNil | |
final case class ::[+H, +T <: HList](head : H, tail : T) extends HList | |
// UbikList or the "Any-Kind" heterogenous list | |
sealed trait UbikList[Args <: HList] | |
trait UbikNil[Args <: HList] extends UbikList[Args] | |
sealed trait UbikCons[Args <: HList] extends UbikList[Args] { | |
type H <: AnyKind | |
type HA | |
type T <: UbikList[Args] with AnyKind | |
type TA | |
def head: HA | |
def tail: TA | |
} | |
// HList1 is equivalent to HList | |
type HList1 = UbikList[HNil] | |
object HList1 { | |
sealed trait HNil1 extends UbikNil[HNil] { | |
def ::[H](h: H) = HList1.::(h, HNil1) | |
} | |
case object HNil1 extends HNil1 | |
case class ::[H0, T0 <: HList1](h: H0, t: T0) extends UbikCons[HNil] { | |
type H = H0 | |
type HA = H0 | |
type T = T0 | |
type TA = T0 | |
val head = h | |
val tail = t | |
def ::[H](h: H) = HList1.::(h, this) | |
} | |
} | |
// HList2 or heterogenous list of structures with one param | |
type HList2[A] = UbikList[A :: HNil] | |
object HList2 { | |
class HNil2[A] extends UbikNil[A :: HNil] { | |
def ::[H[_]](h: H[A]) = HCons2(h, this) | |
} | |
case class HCons2[H0[_], T0[a] <: HList2[a], A](h: H0[A], t: T0[A]) extends UbikCons[A :: HNil] { | |
type H[t] = H0[t] | |
type HA = H0[A] | |
type T[t] = T0[t] | |
type TA = T0[A] | |
val head = h | |
val tail = t | |
def ::[H[_]](h: H[A]) = HCons2[H, ({type l[t] = HCons2[H0, T0, t] })#l, A](h, this) | |
} | |
} | |
// HList3 or heterogenous list of structures with 2 params | |
type HList3[A, B] = UbikList[A :: B :: HNil] | |
object HList3 { | |
class HNil3[A, B] extends UbikNil[A :: B :: HNil] { | |
def ::[H[_, _]](h: H[A, B]) = HCons3(h, this) | |
} | |
case class HCons3[H0[_, _], T0[a, b] <: HList3[a, b], A, B](h: H0[A, B], t: T0[A, B]) extends UbikCons[A :: B :: HNil] { | |
type H[a, b] = H0[a, b] | |
type HA = H0[A, B] | |
type T[a, b] = T0[a, b] | |
type TA = T0[A, B] | |
val head = h | |
val tail = t | |
def ::[H[_, _]](h: H[A, B]) = HCons3[H, ({type l[a, b] = HCons3[H0, T0, a, b] })#l, A, B](h, this) | |
} | |
} | |
import HList1._ | |
val l1 = 5 :: "toto" :: HNil1 | |
val i1: Int = l1.head | |
val s1: String = l1.tail.head | |
val t1: UbikNil[HNil] = l1.tail.tail | |
import HList2._ | |
val l2 = List("tata") :: Bar("toto") :: (new HNil2) | |
val i2: List[String] = l2.head | |
val s2: Bar[String] = l2.tail.head | |
val t2: UbikNil[String :: HNil] = l2.tail.tail | |
import HList3._ | |
val l3 = Map("tata" -> 5L) :: (new Toto[String, Long] {}) :: (new HNil3[String, Long]) | |
val i3: Map[String, Long] = l3.head | |
val s3: Toto[String, Long] = l3.tail.head | |
val t3: UbikNil[String :: Long :: HNil] = l3.tail.tail |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment