mirror of https://github.com/sbt/sbt.git
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:
parent
dbe4b74c10
commit
15fec197c3
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package sbt
|
|||
import java.lang.Runnable
|
||||
import java.util.concurrent.{atomic, Executor, LinkedBlockingQueue}
|
||||
import atomic.{AtomicBoolean, AtomicInteger}
|
||||
import Types.{:+:, Id}
|
||||
import Types.{:+:, ConstK, Id}
|
||||
|
||||
object EvaluationState extends Enumeration {
|
||||
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 {
|
||||
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 u: Uniform[s, T] => new UniformNode(u.inputs map transform.fn[s], u.f)
|
||||
case a: Apply[k,T] => new MixedNode[k,T]( a.alist.transform[Initialize, INode](a.inputs, transform), a.f, a.alist)
|
||||
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 o: Optional[s,T] => o.a match {
|
||||
|
|
@ -155,8 +154,9 @@ abstract class EvaluateSettings[Scope]
|
|||
protected def dependsOn: Seq[INode[_]]
|
||||
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]
|
||||
{
|
||||
protected def dependsOn = in :: Nil
|
||||
|
|
@ -166,14 +166,9 @@ abstract class EvaluateSettings[Scope]
|
|||
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 evaluate0(): Unit = setValue( f(in.map(_.get)) )
|
||||
}
|
||||
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 ) )
|
||||
protected def dependsOn = alist.toList(in)
|
||||
protected def evaluate0(): Unit = setValue( f( alist.transform(in, getValue) ) )
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +1,49 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
import Types._
|
||||
import Classes.Applicative
|
||||
|
||||
/** 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.
|
||||
*
|
||||
* 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]
|
||||
/** Heterogeneous list with each element having type M[T] for some type T.*/
|
||||
sealed trait KList[+M[_]]
|
||||
{
|
||||
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. */
|
||||
type Transform[N[_]] <: KList[N]
|
||||
|
||||
/** Apply the natural transformation `f` to each element. */
|
||||
def transform[N[_]](f: M ~> N): Transform[N]
|
||||
|
||||
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[_]]
|
||||
/** 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]
|
||||
def knil: P[HNil]
|
||||
}
|
||||
final type Transform[N[_]] = KCons[H, tail.Transform[N], N]
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
def foldr[P[_ <: HList],N[X] >: M[X]](f: KFold[N,P]) = f.kcons(head, tail foldr f)
|
||||
final type Transform[N[_]] = KNil
|
||||
final def transform[N[_]](f: Nothing ~> N): Transform[N] = KNil
|
||||
final def toList = Nil
|
||||
final def apply[N[x], Z](f: KNil => Z)(implicit ap: Applicative[N]): N[Z] = ap.pure(f(KNil))
|
||||
final def traverse[N[_], P[_]](f: Nothing ~> (N ∙ P)#l)(implicit np: Applicative[N]): N[KNil] = np.pure(KNil)
|
||||
}
|
||||
|
||||
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 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
|
||||
case object KNil extends KNil {
|
||||
def :^:[M[_], H](h: M[H]): KCons[H, KNil, M] = KCons(h, this)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 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 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 app[HL <: HList, T](inputs: KList[Initialize, HL])(f: HL => T): Initialize[T] = new Apply(f, inputs)
|
||||
def uniform[S,T](inputs: Seq[Initialize[S]])(f: Seq[S] => T): Initialize[T] = new Uniform(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 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 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 mapReferenced(g: MapScoped): Initialize[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 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
|
||||
{
|
||||
|
|
@ -330,34 +333,21 @@ trait Init[Scope]
|
|||
def mapConstant(g: MapConstant) = this
|
||||
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 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 mapInputs(g: Initialize ~> Initialize): Initialize[T] = new Apply(f, inputs transform g)
|
||||
def evaluate(ss: Settings[Scope]) = f(inputs down evaluateT(ss))
|
||||
def mapInputs(g: Initialize ~> Initialize): Initialize[T] = new Apply(f, alist.transform(inputs, g), alist)
|
||||
def evaluate(ss: Settings[Scope]) = f(alist.transform(inputs, evaluateT(ss)))
|
||||
def validateReferenced(g: ValidateRef) =
|
||||
{
|
||||
val tx = inputs transform validateReferencedT(g)
|
||||
val undefs = tx.toList.flatMap(_.left.toSeq.flatten)
|
||||
val tx = alist.transform(inputs, validateReferencedT(g))
|
||||
val undefs = alist.toList(tx).flatMap(_.left.toSeq.flatten)
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ trait TypeFunctions
|
|||
{
|
||||
type Id[X] = X
|
||||
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 ∙[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] }
|
||||
|
|
@ -16,6 +17,7 @@ trait TypeFunctions
|
|||
final val some = new (Id ~> Some) { def apply[T](t: T) = Some(t) }
|
||||
final def idFun[T] = (t: T) => t
|
||||
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 =
|
||||
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] {
|
||||
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 ~>|[A[_],B[_]] = A ~> Compose[Option, B]#Apply
|
||||
|
|
|
|||
|
|
@ -4,15 +4,10 @@
|
|||
package sbt
|
||||
|
||||
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
|
||||
{
|
||||
val :^: = KCons
|
||||
val :+: = HCons
|
||||
type :+:[H, T <: HList] = HCons[H,T]
|
||||
val :+: = HCons
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ object PMapTest
|
|||
mp(Some(3)) = 9
|
||||
val x = Some(3) :^: Some("asdf") :^: KNil
|
||||
val y = x.transform[Id](mp)
|
||||
val z = y.down
|
||||
z match { case 9 :+: "a" :+: HNil => println("true") }
|
||||
assert(y.head == 9)
|
||||
assert(y.tail.head == "a")
|
||||
assert(y.tail.tail == KNil)
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ object SettingsUsage
|
|||
// Define some settings
|
||||
val mySettings: Seq[Setting[_]] = Seq(
|
||||
setting( a3, value( 3 ) ),
|
||||
setting( b4, app(a4 :^: KNil) { case av :+: HNil => av * 3 } ),
|
||||
setting( b4, map(a4)(_ * 3)),
|
||||
update(a5)(_ + 1)
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue