Skip to content

Instantly share code, notes, and snippets.

@mandubian
Created November 30, 2016 00:08
Show Gist options
  • Save mandubian/7d61a9fb7c7a7d09ae43e0a8ac4c6c28 to your computer and use it in GitHub Desktop.
Save mandubian/7d61a9fb7c7a7d09ae43e0a8ac4c6c28 to your computer and use it in GitHub Desktop.
UbikList or abstracting heterogenous list to anykind
// 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