2.10.0-M5, different arity generalization

1. KList[M[_]] now instead of KList[HL <: HList, M[_]]
  a. head, tail work properly in this variant
  b. disadvantage is that full type not easily transformed to new type constructor
2. AList abstracts on K[L[x]], a higher order type constructor.
 A. Instances written for:
  a. KList
  b. Seq[M[T]] for a fixed T
  c. TupleN
  d. single values
  e. operate on one type constructor when nested
 B. Main disadvantage is type inference.  It just doesn't happen for K[L[x]].
    This is mitigated by AList being used internally and rarely needing to construct a K.
This commit is contained in:
Mark Harrah 2012-07-31 11:52:10 -04:00
parent dbe4b74c10
commit 15fec197c3
10 changed files with 308 additions and 134 deletions

211
util/collection/AList.scala Normal file
View File

@ -0,0 +1,211 @@
package sbt
import Classes.Applicative
import Types._
/** An abstraction over (* -> *) -> * with the purpose of abstracting over arity abstractions like KList and TupleN
* as well as homogeneous sequences Seq[M[T]]. */
trait AList[K[L[x]] ]
{
def transform[M[_], N[_]](value: K[M], f: M ~> N): K[N]
def traverse[M[_], N[_], P[_]](value: K[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[K[P]]
def foldr[M[_], A](value: K[M], f: (M[_], A) => A, init: A): A
def toList[M[_]](value: K[M]): List[M[_]] = foldr[M, List[M[_]]](value, _ :: _, Nil)
def apply[M[_], C](value: K[M], f: K[Id] => C)(implicit a: Applicative[M]): M[C] =
a.map(f, traverse[M, M, Id](value, idK[M])(a))
}
object AList
{
type Empty = AList[({ type l[L[x]] = Unit})#l]
val empty: Empty = new Empty {
def transform[M[_], N[_]](in: Unit, f: M ~> N) = ()
def foldr[M[_], T](in: Unit, f: (M[_], T) => T, init: T) = init
override def apply[M[_], C](in: Unit, f: Unit => C)(implicit app: Applicative[M]): M[C] = app.pure( f( () ) )
def traverse[M[_], N[_], P[_]](in: Unit, f: M ~> (N P)#l)(implicit np: Applicative[N]): N[Unit] = np.pure( () )
}
type SeqList[T] = AList[({ type l[L[x]] = List[L[T]] })#l]
def seq[T]: SeqList[T] = new SeqList[T]
{
def transform[M[_], N[_]](s: List[M[T]], f: M ~> N) = s.map(f.fn[T])
def foldr[M[_], A](s: List[M[T]], f: (M[_], A) => A, init: A): A = (init /: s.reverse)( (t, m) => f(m,t))
override def apply[M[_], C](s: List[M[T]], f: List[T] => C)(implicit ap: Applicative[M]): M[C] =
{
def loop[V](in: List[M[T]], g: List[T] => V): M[V] =
in match {
case Nil => ap.pure(g(Nil))
case x :: xs =>
val h = (ts: List[T]) => (t: T) => g(t :: ts)
ap.apply( loop(xs, h), x )
}
loop(s, f)
}
def traverse[M[_], N[_], P[_]](s: List[M[T]], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[List[P[T]]] = ???
}
def klist[KL[M[_]] <: KList[M] { type Transform[N[_]] = KL[N] }]: AList[KL] = new AList[KL] {
def transform[M[_], N[_]](k: KL[M], f: M ~> N) = k.transform(f)
def foldr[M[_], T](k: KL[M], f: (M[_], T) => T, init: T): T = k.foldr(f, init)
override def apply[M[_], C](k: KL[M], f: KL[Id] => C)(implicit app: Applicative[M]): M[C] = k.apply(f)(app)
def traverse[M[_], N[_], P[_]](k: KL[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[KL[P]] = k.traverse[N,P](f)(np)
}
type Single[A] = AList[({ type l[L[x]] = L[A]})#l]
def single[A]: Single[A] = new Single[A] {
def transform[M[_], N[_]](a: M[A], f: M ~> N) = f(a)
def foldr[M[_], T](a: M[A], f: (M[_], T) => T, init: T): T = f(a, init)
def traverse[M[_], N[_], P[_]](a: M[A], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[P[A]] = f(a)
}
type ASplit[K[L[x]], B[x]] = AList[ ({ type l[L[x]] = K[ (L B)#l] })#l ]
def asplit[ K[L[x]], B[x] ](base: AList[K]): ASplit[K,B] = new ASplit[K, B]
{
type Split[ L[x] ] = K[ (L B)#l ]
def transform[M[_], N[_]](value: Split[M], f: M ~> N): Split[N] =
base.transform[(M B)#l, (N B)#l](value, nestCon[M,N,B](f))
def traverse[M[_], N[_], P[_]](value: Split[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[Split[P]] =
{
val g = nestCon[M, (N P)#l, B](f)
base.traverse[(M B)#l, N, (P B)#l](value, g)(np)
}
def foldr[M[_], A](value: Split[M], f: (M[_], A) => A, init: A): A =
base.foldr[(M B)#l, A](value, f, init)
}
// TODO: auto-generate
sealed trait T2K[A,B] { type l[L[x]] = (L[A], L[B]) }
type T2List[A,B] = AList[T2K[A,B]#l]
def tuple2[A, B]: T2List[A,B] = new T2List[A,B]
{
type T2[M[_]] = (M[A], M[B])
def transform[M[_], N[_]](t: T2[M], f: M ~> N): T2[N] = (f(t._1), f(t._2))
def foldr[M[_], T](t: T2[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, init))
def traverse[M[_], N[_], P[_]](t: T2[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T2[P]] =
{
val g = (Tuple2.apply[P[A], P[B]] _).curried
np.apply( np.map(g, f(t._1)), f(t._2) )
}
}
sealed trait T3K[A,B,C] { type l[L[x]] = (L[A], L[B], L[C]) }
type T3List[A,B,C] = AList[T3K[A,B,C]#l]
def tuple3[A, B, C]: T3List[A,B,C] = new T3List[A,B,C]
{
type T3[M[_]] = (M[A], M[B], M[C])
def transform[M[_], N[_]](t: T3[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3))
def foldr[M[_], T](t: T3[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, init)))
def traverse[M[_], N[_], P[_]](t: T3[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T3[P]] =
{
val g = (Tuple3.apply[P[A],P[B],P[C]] _).curried
np.apply( np.apply( np.map(g, f(t._1)), f(t._2) ), f(t._3) )
}
}
sealed trait T4K[A,B,C,D] { type l[L[x]] = (L[A], L[B], L[C], L[D]) }
type T4List[A,B,C,D] = AList[T4K[A,B,C,D]#l]
def tuple4[A, B, C, D]: T4List[A,B,C,D] = new T4List[A,B,C,D]
{
type T4[M[_]] = (M[A], M[B], M[C], M[D])
def transform[M[_], N[_]](t: T4[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4))
def foldr[M[_], T](t: T4[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, init))))
def traverse[M[_], N[_], P[_]](t: T4[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T4[P]] =
{
val g = (Tuple4.apply[P[A], P[B], P[C], P[D]] _).curried
np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4))
}
}
sealed trait T5K[A,B,C,D,E] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E]) }
type T5List[A,B,C,D,E] = AList[T5K[A,B,C,D,E]#l]
def tuple5[A, B, C, D, E]: T5List[A,B,C,D,E] = new T5List[A,B,C,D,E] {
type T5[M[_]] = (M[A], M[B], M[C], M[D], M[E])
def transform[M[_], N[_]](t: T5[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5))
def foldr[M[_], T](t: T5[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, init)))))
def traverse[M[_], N[_], P[_]](t: T5[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T5[P]] =
{
val g = (Tuple5.apply[P[A],P[B],P[C],P[D],P[E]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5) )
}
}
sealed trait T6K[A,B,C,D,E,F] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F]) }
type T6List[A,B,C,D,E,F] = AList[T6K[A,B,C,D,E,F]#l]
def tuple6[A, B, C, D, E, F]: T6List[A,B,C,D,E,F] = new T6List[A,B,C,D,E,F] {
type T6[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F])
def transform[M[_], N[_]](t: T6[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6))
def foldr[M[_], T](t: T6[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, init))))))
def traverse[M[_], N[_], P[_]](t: T6[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T6[P]] =
{
val g = (Tuple6.apply[P[A],P[B],P[C],P[D],P[E],P[F]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6))
}
}
sealed trait T7K[A,B,C,D,E,F,G] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F], L[G]) }
type T7List[A,B,C,D,E,F,G] = AList[T7K[A,B,C,D,E,F,G]#l]
def tuple7[A,B,C,D,E,F,G]: T7List[A,B,C,D,E,F,G] = new T7List[A,B,C,D,E,F,G] {
type T7[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G])
def transform[M[_], N[_]](t: T7[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6), f(t._7))
def foldr[M[_], T](t: T7[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, f(t._7, init)))))))
def traverse[M[_], N[_], P[_]](t: T7[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T7[P]] =
{
val g = (Tuple7.apply[P[A],P[B],P[C],P[D],P[E],P[F],P[G]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6)), f(t._7))
}
}
sealed trait T8K[A,B,C,D,E,F,G,H] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F], L[G], L[H]) }
type T8List[A,B,C,D,E,F,G,H] = AList[T8K[A,B,C,D,E,F,G,H]#l]
def tuple8[A,B,C,D,E,F,G,H]: T8List[A,B,C,D,E,F,G,H] = new T8List[A,B,C,D,E,F,G,H] {
type T8[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G], M[H])
def transform[M[_], N[_]](t: T8[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6), f(t._7), f(t._8))
def foldr[M[_], T](t: T8[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, f(t._7, f(t._8, init))))))))
def traverse[M[_], N[_], P[_]](t: T8[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T8[P]] =
{
val g = (Tuple8.apply[P[A],P[B],P[C],P[D],P[E],P[F],P[G],P[H]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6)), f(t._7)), f(t._8))
}
}
sealed trait T9K[A,B,C,D,E,F,G,H,I] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F], L[G], L[H], L[I]) }
type T9List[A,B,C,D,E,F,G,H,I] = AList[T9K[A,B,C,D,E,F,G,H,I]#l]
def tuple9[A,B,C,D,E,F,G,H,I]: T9List[A,B,C,D,E,F,G,H,I] = new T9List[A,B,C,D,E,F,G,H,I] {
type T9[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G], M[H], M[I])
def transform[M[_], N[_]](t: T9[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6), f(t._7), f(t._8), f(t._9))
def foldr[M[_], T](t: T9[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, f(t._7, f(t._8, f(t._9, init)))))))))
def traverse[M[_], N[_], P[_]](t: T9[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T9[P]] =
{
val g = (Tuple9.apply[P[A],P[B],P[C],P[D],P[E],P[F],P[G],P[H],P[I]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6)), f(t._7)), f(t._8)), f(t._9))
}
}
sealed trait T10K[A,B,C,D,E,F,G,H,I,J] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F], L[G], L[H], L[I], L[J]) }
type T10List[A,B,C,D,E,F,G,H,I,J] = AList[T10K[A,B,C,D,E,F,G,H,I,J]#l]
def tuple10[A,B,C,D,E,F,G,H,I,J]: T10List[A,B,C,D,E,F,G,H,I,J] = new T10List[A,B,C,D,E,F,G,H,I,J] {
type T10[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G], M[H], M[I], M[J])
def transform[M[_], N[_]](t: T10[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6), f(t._7), f(t._8), f(t._9), f(t._10))
def foldr[M[_], T](t: T10[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, f(t._7, f(t._8, f(t._9, f(t._10, init))))))))))
def traverse[M[_], N[_], P[_]](t: T10[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T10[P]] =
{
val g = (Tuple10.apply[P[A],P[B],P[C],P[D],P[E],P[F],P[G],P[H],P[I],P[J]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6)), f(t._7)), f(t._8)), f(t._9)), f(t._10))
}
}
sealed trait T11K[A,B,C,D,E,F,G,H,I,J,K] { type l[L[x]] = (L[A], L[B], L[C], L[D], L[E], L[F], L[G], L[H], L[I], L[J], L[K]) }
type T11List[A,B,C,D,E,F,G,H,I,J,K] = AList[T11K[A,B,C,D,E,F,G,H,I,J,K]#l]
def tuple11[A,B,C,D,E,F,G,H,I,J,K]: T11List[A,B,C,D,E,F,G,H,I,J,K] = new T11List[A,B,C,D,E,F,G,H,I,J,K] {
type T11[M[_]] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G], M[H], M[I], M[J], M[K])
def transform[M[_], N[_]](t: T11[M], f: M ~> N) = (f(t._1), f(t._2), f(t._3), f(t._4), f(t._5), f(t._6), f(t._7), f(t._8), f(t._9), f(t._10), f(t._11))
def foldr[M[_], T](t: T11[M], f: (M[_], T) => T, init: T): T = f(t._1, f(t._2, f(t._3, f(t._4, f(t._5, f(t._6, f(t._7, f(t._8, f(t._9, f(t._10, f(t._11,init)))))))))))
def traverse[M[_], N[_], P[_]](t: T11[M], f: M ~> (N P)#l)(implicit np: Applicative[N]): N[T11[P]] =
{
val g = (Tuple11.apply[P[A],P[B],P[C],P[D],P[E],P[F],P[G],P[H],P[I],P[J],P[K]] _ ).curried
np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.apply( np.map(g, f(t._1)), f(t._2)), f(t._3)), f(t._4)), f(t._5)), f(t._6)), f(t._7)), f(t._8)), f(t._9)), f(t._10)), f(t._11))
}
}
}

View File

@ -0,0 +1,27 @@
package sbt
object Classes
{
trait Applicative[M[_]]
{
def apply[S,T](f: M[S => T], v: M[S]): M[T]
def pure[S](s: => S): M[S]
def map[S, T](f: S => T, v: M[S]): M[T]
}
trait Monad[M[_]] extends Applicative[M]
{
def flatten[T](m: M[M[T]]): M[T]
}
implicit val optionMonad: Monad[Option] = new Monad[Option] {
def apply[S,T](f: Option[S => T], v: Option[S]) = (f, v) match { case (Some(fv), Some(vv)) => Some(fv(vv)); case _ => None }
def pure[S](s: => S) = Some(s)
def map[S, T](f: S => T, v: Option[S]) = v map f
def flatten[T](m: Option[Option[T]]): Option[T] = m.flatten
}
implicit val listMonad: Monad[List] = new Monad[List] {
def apply[S,T](f: List[S => T], v: List[S]) = for(fv <- f; vv <- v) yield fv(vv)
def pure[S](s: => S) = s :: Nil
def map[S, T](f: S => T, v: List[S]) = v map f
def flatten[T](m: List[List[T]]): List[T] = m.flatten
}
}

View File

@ -3,7 +3,7 @@ package sbt
import java.lang.Runnable import java.lang.Runnable
import java.util.concurrent.{atomic, Executor, LinkedBlockingQueue} import java.util.concurrent.{atomic, Executor, LinkedBlockingQueue}
import atomic.{AtomicBoolean, AtomicInteger} import atomic.{AtomicBoolean, AtomicInteger}
import Types.{:+:, Id} import Types.{:+:, ConstK, Id}
object EvaluationState extends Enumeration { object EvaluationState extends Enumeration {
val New, Blocked, Ready, Calling, Evaluated = Value val New, Blocked, Ready, Calling, Evaluated = Value
@ -24,8 +24,7 @@ abstract class EvaluateSettings[Scope]
private[this] val transform: Initialize ~> INode = new (Initialize ~> INode) { def apply[T](i: Initialize[T]): INode[T] = i match { private[this] val transform: Initialize ~> INode = new (Initialize ~> INode) { def apply[T](i: Initialize[T]): INode[T] = i match {
case k: Keyed[s, T] => single(getStatic(k.scopedKey), k.transform) case k: Keyed[s, T] => single(getStatic(k.scopedKey), k.transform)
case a: Apply[hl,T] => new MixedNode(a.inputs transform transform, a.f) case a: Apply[k,T] => new MixedNode[k,T]( a.alist.transform[Initialize, INode](a.inputs, transform), a.f, a.alist)
case u: Uniform[s, T] => new UniformNode(u.inputs map transform.fn[s], u.f)
case b: Bind[s,T] => new BindNode[s,T]( transform(b.in), x => transform(b.f(x))) case b: Bind[s,T] => new BindNode[s,T]( transform(b.in), x => transform(b.f(x)))
case v: Value[T] => constant(v.value) case v: Value[T] => constant(v.value)
case o: Optional[s,T] => o.a match { case o: Optional[s,T] => o.a match {
@ -155,8 +154,9 @@ abstract class EvaluateSettings[Scope]
protected def dependsOn: Seq[INode[_]] protected def dependsOn: Seq[INode[_]]
protected def evaluate0(): Unit protected def evaluate0(): Unit
} }
private[this] def constant[T](f: () => T): INode[T] = new MixedNode[HNil, T](KNil, _ => f())
private[this] def single[S,T](in: INode[S], f: S => T): INode[T] = new MixedNode[S :+: HNil, T](in :^: KNil, hl => f(hl.head)) private[this] def constant[T](f: () => T): INode[T] = new MixedNode[ConstK[Unit]#l, T]((), _ => f(), AList.empty)
private[this] def single[S,T](in: INode[S], f: S => T): INode[T] = new MixedNode[ ({ type l[L[x]] = L[S] })#l, T](in, f, AList.single[S])
private[this] final class BindNode[S,T](in: INode[S], f: S => INode[T]) extends INode[T] private[this] final class BindNode[S,T](in: INode[S], f: S => INode[T]) extends INode[T]
{ {
protected def dependsOn = in :: Nil protected def dependsOn = in :: Nil
@ -166,14 +166,9 @@ abstract class EvaluateSettings[Scope]
setValue(value) setValue(value)
} }
} }
private[this] final class UniformNode[S,T](in: Seq[INode[S]], f: Seq[S] => T) extends INode[T] private[this] final class MixedNode[K[L[x]], T](in: K[INode], f: K[Id] => T, alist: AList[K]) extends INode[T]
{ {
protected def dependsOn = in protected def dependsOn = alist.toList(in)
protected def evaluate0(): Unit = setValue( f(in.map(_.get)) ) protected def evaluate0(): Unit = setValue( f( alist.transform(in, getValue) ) )
}
private[this] final class MixedNode[HL <: HList, T](in: KList[INode, HL], f: HL => T) extends INode[T]
{
protected def dependsOn = in.toList
protected def evaluate0(): Unit = setValue( f( in down getValue ) )
} }
} }

View File

@ -1,76 +1,49 @@
/* sbt -- Simple Build Tool
* Copyright 2010 Mark Harrah
*/
package sbt package sbt
import Types._ import Types._
import Classes.Applicative
/** A higher-order heterogeneous list. It has a type constructor M[_] and /** Heterogeneous list with each element having type M[T] for some type T.*/
* type parameters HL. The underlying data is M applied to each type parameter. sealed trait KList[+M[_]]
* Explicitly tracking M[_] allows performing natural transformations or ensuring
* all data conforms to some common type.
*
* For background, see
* http://apocalisp.wordpress.com/2010/11/01/type-level-programming-in-scala-part-8a-klist%C2%A0motivation/
*/
sealed trait KList[+M[_], HL <: HList]
{ {
type Raw = HL type Transform[N[_]] <: KList[N]
/** Transform to the underlying HList type.*/
def down(implicit ev: M ~> Id): HL /** Apply the natural transformation `f` to each element. */
/** Apply a natural transformation. */ def transform[N[_]](f: M ~> N): Transform[N]
def transform[N[_]](f: M ~> N): KList[N, HL]
/** Convert to a List. */ def foldr[T](f: (M[_], T) => T, init: T): T = init // had trouble defining it in KNil
def apply[N[x] >: M[x], Z](f: Transform[Id] => Z)(implicit ap: Applicative[N]): N[Z]
def traverse[N[_], P[_]](f: M ~> (N P)#l)(implicit np: Applicative[N]): N[Transform[P]]
def toList: List[M[_]] 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]] final case class KCons[H, +T <: KList[M], +M[_]](head: M[H], tail: T) extends KList[M]
{ {
def kcons[H,T <: HList](h: M[H], acc: P[T]): P[H :+: T] final type Transform[N[_]] = KCons[H, tail.Transform[N], N]
def knil: P[HNil]
}
final case class KCons[H, T <: HList, +M[_]](head: M[H], tail: KList[M,T]) extends KList[M, H :+: T] def transform[N[_]](f: M ~> N) = KCons(f(head), tail.transform(f))
def toList: List[M[_]] = head :: tail.toList
def apply[N[x] >: M[x], Z](f: Transform[Id] => Z)(implicit ap: Applicative[N]): N[Z] =
{
val g = (t: tail.Transform[Id]) => (h: H) =>f( KCons[H, tail.Transform[Id], Id](h, t) )
ap.apply( tail.apply[N, H => Z](g), head )
}
def traverse[N[_], P[_]](f: M ~> (N P)#l)(implicit np: Applicative[N]): N[Transform[P]] =
{
val tt: N[tail.Transform[P]] = tail.traverse[N,P](f)
val g = (t: tail.Transform[P]) => (h: P[H]) => KCons(h, t)
np.apply(np.map(g, tt), f(head))
}
def :^:[A,N[x] >: M[x]](h: N[A]) = KCons(h, this)
override def foldr[T](f: (M[_], T) => T, init: T): T = f(head, tail.foldr(f, init))
}
sealed abstract class KNil extends KList[Nothing]
{ {
def down(implicit f: M ~> Id) = HCons(f(head), tail down f) final type Transform[N[_]] = KNil
def transform[N[_]](f: M ~> N) = KCons( f(head), tail transform f ) final def transform[N[_]](f: Nothing ~> N): Transform[N] = KNil
// prepend final def toList = Nil
def :^: [N[X] >: M[X], G](g: N[G]) = KCons(g, this) final def apply[N[x], Z](f: KNil => Z)(implicit ap: Applicative[N]): N[Z] = ap.pure(f(KNil))
def toList = head :: tail.toList final def traverse[N[_], P[_]](f: Nothing ~> (N P)#l)(implicit np: Applicative[N]): N[KNil] = np.pure(KNil)
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)
} }
case object KNil extends KNil {
sealed class KNil extends KList[Nothing, HNil] def :^:[M[_], H](h: M[H]): KCons[H, KNil, M] = KCons(h, this)
{
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 foldr[P[_ <: HList],N[_]](f: KFold[N,P]) = f.knil
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))
// 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
} }

View File

@ -61,10 +61,12 @@ trait Init[Scope]
def setting[T](key: ScopedKey[T], init: Initialize[T], pos: SourcePosition = NoPosition): Setting[T] = new Setting[T](key, init, pos) def setting[T](key: ScopedKey[T], init: Initialize[T], pos: SourcePosition = NoPosition): Setting[T] = new Setting[T](key, init, pos)
def value[T](value: => T): Initialize[T] = new Value(value _) def value[T](value: => T): Initialize[T] = new Value(value _)
def optional[T,U](i: Initialize[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(i), f) def optional[T,U](i: Initialize[T])(f: Option[T] => U): Initialize[U] = new Optional(Some(i), f)
def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, app(key :^: KNil)(hl => f(hl.head)), NoPosition) def update[T](key: ScopedKey[T])(f: T => T): Setting[T] = new Setting[T](key, map(key)(f), NoPosition)
def bind[S,T](in: Initialize[S])(f: S => Initialize[T]): Initialize[T] = new Bind(f, in) def bind[S,T](in: Initialize[S])(f: S => Initialize[T]): Initialize[T] = new Bind(f, in)
def app[HL <: HList, T](inputs: KList[Initialize, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs) def map[S,T](in: Initialize[S])(f: S => T): Initialize[T] = new Apply[ ({ type l[L[x]] = L[S] })#l, T](f, in, AList.single[S])
def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(f, inputs) def app[K[L[x]], T](inputs: K[Initialize])(f: K[Id] => T)(implicit alist: AList[K]): Initialize[T] = new Apply[K, T](f, inputs, alist)
def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] =
new Apply[({ type l[L[x]] = List[L[S]] })#l, T](f, inputs.toList, AList.seq[S])
def empty(implicit delegates: Scope => Seq[Scope]): Settings[Scope] = new Settings0(Map.empty, delegates) def empty(implicit delegates: Scope => Seq[Scope]): Settings[Scope] = new Settings0(Map.empty, delegates)
def asTransform(s: Settings[Scope]): ScopedKey ~> Id = new (ScopedKey ~> Id) { def asTransform(s: Settings[Scope]): ScopedKey ~> Id = new (ScopedKey ~> Id) {
@ -219,11 +221,12 @@ trait Init[Scope]
def apply[S](g: T => S): Initialize[S] def apply[S](g: T => S): Initialize[S]
def mapReferenced(g: MapScoped): Initialize[T] def mapReferenced(g: MapScoped): Initialize[T]
def validateReferenced(g: ValidateRef): ValidatedInit[T] def validateReferenced(g: ValidateRef): ValidatedInit[T]
def zip[S](o: Initialize[S]): Initialize[(T,S)] = zipWith(o)((x,y) => (x,y))
def zipWith[S,U](o: Initialize[S])(f: (T,S) => U): Initialize[U] =
new Apply[T :+: S :+: HNil, U]( { case t :+: s :+: HNil => f(t,s)}, this :^: o :^: KNil)
def mapConstant(g: MapConstant): Initialize[T] def mapConstant(g: MapConstant): Initialize[T]
def evaluate(map: Settings[Scope]): T def evaluate(map: Settings[Scope]): T
def zip[S](o: Initialize[S]): Initialize[(T,S)] = zipTupled(o)(idFun)
def zipWith[S,U](o: Initialize[S])(f: (T,S) => U): Initialize[U] = zipTupled(o)(f.tupled)
private[this] def zipTupled[S,U](o: Initialize[S])(f: ((T,S)) => U): Initialize[U] =
new Apply[({ type l[L[x]] = (L[T], L[S]) })#l, U](f, (this, o), AList.tuple2[T,S])
} }
object Initialize object Initialize
{ {
@ -330,34 +333,21 @@ trait Init[Scope]
def mapConstant(g: MapConstant) = this def mapConstant(g: MapConstant) = this
def evaluate(map: Settings[Scope]): T = value() def evaluate(map: Settings[Scope]): T = value()
} }
private[sbt] final class Apply[HL <: HList, T](val f: HL => T, val inputs: KList[Initialize, HL]) extends Initialize[T] private[sbt] final class Apply[K[L[x]], T](val f: K[Id] => T, val inputs: K[Initialize], val alist: AList[K]) extends Initialize[T]
{ {
def dependencies = deps(inputs.toList) def dependencies = deps(alist.toList(inputs))
def mapReferenced(g: MapScoped) = mapInputs( mapReferencedT(g) ) def mapReferenced(g: MapScoped) = mapInputs( mapReferencedT(g) )
def apply[S](g: T => S) = new Apply(g compose f, inputs) def apply[S](g: T => S) = new Apply(g compose f, inputs, alist)
def mapConstant(g: MapConstant) = mapInputs( mapConstantT(g) ) def mapConstant(g: MapConstant) = mapInputs( mapConstantT(g) )
def mapInputs(g: Initialize ~> Initialize): Initialize[T] = new Apply(f, inputs transform g) def mapInputs(g: Initialize ~> Initialize): Initialize[T] = new Apply(f, alist.transform(inputs, g), alist)
def evaluate(ss: Settings[Scope]) = f(inputs down evaluateT(ss)) def evaluate(ss: Settings[Scope]) = f(alist.transform(inputs, evaluateT(ss)))
def validateReferenced(g: ValidateRef) = def validateReferenced(g: ValidateRef) =
{ {
val tx = inputs transform validateReferencedT(g) val tx = alist.transform(inputs, validateReferencedT(g))
val undefs = tx.toList.flatMap(_.left.toSeq.flatten) val undefs = alist.toList(tx).flatMap(_.left.toSeq.flatten)
val get = new (ValidatedInit ~> Initialize) { def apply[T](vr: ValidatedInit[T]) = vr.right.get } val get = new (ValidatedInit ~> Initialize) { def apply[T](vr: ValidatedInit[T]) = vr.right.get }
if(undefs.isEmpty) Right(new Apply(f, tx transform get)) else Left(undefs) if(undefs.isEmpty) Right(new Apply(f, alist.transform(tx, get), alist)) else Left(undefs)
} }
} }
private[sbt] final class Uniform[S, T](val f: Seq[S] => T, val inputs: Seq[Initialize[S]]) extends Initialize[T]
{
def dependencies = deps(inputs)
def mapReferenced(g: MapScoped) = new Uniform(f, inputs map mapReferencedT(g).fn)
def validateReferenced(g: ValidateRef) =
{
val (undefs, ok) = Util.separateE(inputs map validateReferencedT(g).fn )
if(undefs.isEmpty) Right( new Uniform(f, ok) ) else Left(undefs.flatten)
}
def apply[S](g: T => S) = new Uniform(g compose f, inputs)
def mapConstant(g: MapConstant) = new Uniform(f, inputs map mapConstantT(g).fn)
def evaluate(ss: Settings[Scope]) = f(inputs map evaluateT(ss).fn )
}
private def remove[T](s: Seq[T], v: T) = s filterNot (_ == v) private def remove[T](s: Seq[T], v: T) = s filterNot (_ == v)
} }

View File

@ -7,6 +7,7 @@ trait TypeFunctions
{ {
type Id[X] = X type Id[X] = X
sealed trait Const[A] { type Apply[B] = A } sealed trait Const[A] { type Apply[B] = A }
sealed trait ConstK[A] { type l[L[x]] = A }
sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] } sealed trait Compose[A[_], B[_]] { type Apply[T] = A[B[T]] }
sealed trait [A[_], B[_]] { type l[T] = A[B[T]] } sealed trait [A[_], B[_]] { type l[T] = A[B[T]] }
sealed trait P1of2[M[_,_], A] { type Apply[B] = M[A,B]; type Flip[B] = M[B, A] } sealed trait P1of2[M[_,_], A] { type Apply[B] = M[A,B]; type Flip[B] = M[B, A] }
@ -16,6 +17,7 @@ trait TypeFunctions
final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) } final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) }
final def idFun[T] = (t: T) => t final def idFun[T] = (t: T) => t
final def const[A,B](b: B): A=> B = _ => b final def const[A,B](b: B): A=> B = _ => b
final def idK[M[_]]: M ~> M = new (M ~> M) { def apply[T](m: M[T]): M[T] = m }
def nestCon[M[_], N[_], G[_]](f: M ~> N): (M G)#l ~> (N G)#l = def nestCon[M[_], N[_], G[_]](f: M ~> N): (M G)#l ~> (N G)#l =
f.asInstanceOf[(M G)#l ~> (N G)#l] // implemented with a cast to avoid extra object+method call. castless version: f.asInstanceOf[(M G)#l ~> (N G)#l] // implemented with a cast to avoid extra object+method call. castless version:
@ -26,7 +28,6 @@ trait TypeFunctions
implicit def toFn1[A,B](f: A => B): Fn1[A,B] = new Fn1[A,B] { implicit def toFn1[A,B](f: A => B): Fn1[A,B] = new Fn1[A,B] {
def [C](g: C => A) = f compose g def [C](g: C => A) = f compose g
} }
def idK[M[_]]: M ~> M = new (M ~> M) { def apply[T](m: M[T]): M[T] = m }
type Endo[T] = T=>T type Endo[T] = T=>T
type ~>|[A[_],B[_]] = A ~> Compose[Option, B]#Apply type ~>|[A[_],B[_]] = A ~> Compose[Option, B]#Apply

View File

@ -4,15 +4,10 @@
package sbt package sbt
object Types extends Types object Types extends Types
{
implicit def hconsToK[M[_], H, T <: HList](h: M[H] :+: T)(implicit mt: T => KList[M, T]): KList[M, H :+: T] =
KCons[H, T, M](h.head, mt(h.tail) )
implicit def hnilToK(hnil: HNil): KNil = KNil
}
trait Types extends TypeFunctions trait Types extends TypeFunctions
{ {
val :^: = KCons val :^: = KCons
val :+: = HCons
type :+:[H, T <: HList] = HCons[H,T] type :+:[H, T <: HList] = HCons[H,T]
val :+: = HCons
} }

View File

@ -1,19 +0,0 @@
/* sbt -- Simple Build Tool
* Copyright 2010 Mark Harrah
*/
package sbt
import Types._
object KTest {
val f = new (Option ~> List) { def apply[T](o: Option[T]): List[T] = o.toList }
val x = Some(3) :^: Some("asdf") :^: KNil
val y = x transform f
val m1a = y match { case List(3) :^: List("asdf") :^: KNil => println("true") }
val m1b = (List(3) :^: KNil) match { case yy :^: KNil => println("true") }
val head = new (List ~> Id) { def apply[T](xs: List[T]): T = xs.head }
val z = y down head
val m2 = z match { case 3 :+: "asdf" :+: HNil => println("true") }
}

View File

@ -13,6 +13,7 @@ object PMapTest
mp(Some(3)) = 9 mp(Some(3)) = 9
val x = Some(3) :^: Some("asdf") :^: KNil val x = Some(3) :^: Some("asdf") :^: KNil
val y = x.transform[Id](mp) val y = x.transform[Id](mp)
val z = y.down assert(y.head == 9)
z match { case 9 :+: "a" :+: HNil => println("true") } assert(y.tail.head == "a")
assert(y.tail.tail == KNil)
} }

View File

@ -49,7 +49,7 @@ object SettingsUsage
// Define some settings // Define some settings
val mySettings: Seq[Setting[_]] = Seq( val mySettings: Seq[Setting[_]] = Seq(
setting( a3, value( 3 ) ), setting( a3, value( 3 ) ),
setting( b4, app(a4 :^: KNil) { case av :+: HNil => av * 3 } ), setting( b4, map(a4)(_ * 3)),
update(a5)(_ + 1) update(a5)(_ + 1)
) )