From 2f4169026972ee82cbcf6055bf886c6e2e1bb00f Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 28 Jan 2011 21:07:29 -0500 Subject: [PATCH] KList updates - exchange variance annotations on KList for a bounded existential in KList.toList - add foldr (reason for dropping variance annotations) - add functions stating equivalence between + KList[M,H :+: T] and KCons[H,T,M] + KList[M,HNil] and KNil --- util/collection/KList.scala | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/util/collection/KList.scala b/util/collection/KList.scala index aa9662917..8035a4f2f 100644 --- a/util/collection/KList.scala +++ b/util/collection/KList.scala @@ -9,7 +9,7 @@ import Types._ * 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] +sealed trait KList[+M[_], HL <: HList] { type Raw = HL /** Transform to the underlying HList type.*/ @@ -20,6 +20,13 @@ sealed trait KList[+M[_], +HL <: HList] def toList: List[M[_]] /** Convert to an HList. */ def combine[N[X] >: M[X]]: HL#Wrap[N] + + def foldr[P[_ <: HList],N[X] >: M[X]](f: KFold[N,P]): P[HL] +} +trait KFold[M[_],P[_ <: HList]] +{ + def kcons[H,T <: HList](h: M[H], acc: P[T]): P[H :+: T] + def knil: P[HNil] } final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) extends KList[M, H :+: T] @@ -33,6 +40,8 @@ final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) exten def combine[N[X] >: M[X]]: (H :+: T)#Wrap[N] = HCons(head, tail.combine) override def toString = head + " :^: " + tail.toString + + def foldr[P[_ <: HList],N[X] >: M[X]](f: KFold[N,P]) = f.kcons(head, tail foldr f) } sealed class KNil extends KList[Nothing, HNil] @@ -42,6 +51,7 @@ sealed class KNil extends KList[Nothing, HNil] def :^: [M[_], H](h: M[H]) = KCons(h, this) def toList = Nil def combine[N[X]] = HNil + override def foldr[P[_ <: HList],N[_]](f: KFold[N,P]) = f.knil override def toString = "KNil" } object KNil extends KNil @@ -51,5 +61,12 @@ 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)) + def fromList[M[_]](s: Seq[M[_]]): KList[M, _ <: HList] = if(s.isEmpty) KNil else KCons(s.head, fromList(s.tail)) + + // haven't found a way to convince scalac that KList[M, H :+: T] implies KCons[H,T,M] + // Therefore, this method exists to put the cast in one location. + implicit def kcons[H, T <: HList, M[_]](kl: KList[M, H :+: T]): KCons[H,T,M] = + kl.asInstanceOf[KCons[H,T,M]] + // haven't need this, but for symmetry with kcons: + implicit def knil[M[_]](kl: KList[M, HNil]): KNil = KNil }