/* sbt -- Simple Build Tool * Copyright 2010 Mark Harrah */ package sbt import Types._ /** A higher-order heterogeneous list. It has a type constructor M[_] and * type parameters HL. The underlying data is M applied to each type parameter. * Explicitly tracking M[_] allows performing natural transformations or ensuring * all data conforms to some common type. */ sealed trait KList[+M[_], +HL <: HList] { type Raw = HL /** Transform to the underlying HList type.*/ def down(implicit ev: M ~> Id): HL /** Apply a natural transformation. */ def transform[N[_]](f: M ~> N): KList[N, HL] /** Convert to a List. */ def toList: List[M[_]] /** Convert to an HList. */ def combine[N[X] >: M[X]]: HL#Wrap[N] } final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) extends KList[M, H :+: T] { def down(implicit f: M ~> Id) = HCons(f(head), tail down f) def transform[N[_]](f: M ~> N) = KCons( f(head), tail transform f ) // prepend def :^: [N[X] >: M[X], G](g: N[G]) = KCons(g, this) def toList = head :: tail.toList def combine[N[X] >: M[X]]: (H :+: T)#Wrap[N] = HCons(head, tail.combine) override def toString = head + " :^: " + tail.toString } sealed class KNil extends KList[Nothing, HNil] { def down(implicit f: Nothing ~> Id) = HNil def transform[N[_]](f: Nothing ~> N) = KNil def :^: [M[_], H](h: M[H]) = KCons(h, this) def toList = Nil def combine[N[X]] = HNil override def toString = "KNil" } object KNil extends KNil object KList { // nicer alias for pattern matching val :^: = KCons def fromList[M[_]](s: Seq[M[_]]): KList[M, HList] = if(s.isEmpty) KNil else KCons(s.head, fromList(s.tail)) }