Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MList, HList.toList, ~> literals

  • Loading branch information...
commit dbd1d67a738a60a9716e1e3ffca879e45c44c079 1 parent 04abf6a
@harrah authored
Showing with 108 additions and 0 deletions.
  1. +7 −0 HList.scala
  2. +4 −0 HListTest.scala
  3. +66 −0 MList.scala
  4. +31 −0 Transform.scala
View
7 HList.scala
@@ -64,6 +64,10 @@ object HList extends HApplyOps with UnzipOps
def unapply[H,T<:HList](list: HCons[H,T]) = Some((list.head,list.tail))
}
+ def toList[S] = new ToList[S]
+ implicit def listHCons[H <: S, T <: HList, S](implicit f: T => List[S]): (H :: T) => List[S] = hc => hc.head :: f(hc.tail)
+ implicit def listHNil[S]: HNil => List[S] = hn => Nil
+
import Indexed._
type :::[A <: HList, B <: HList] = A#Foldr[HList, AppHCons.type, B]
@@ -128,4 +132,7 @@ sealed trait HListOps[B <: HList] {
def ::[A](b: A): A :: B
def zip[C <: HList, R <: HList](c: C)(implicit hzip: HZip[B,C, R]): R
+}
+final class ToList[S] {
+ def apply[H <: HList](h: H)(implicit f: H => List[S]): List[S] = f(h)
}
View
4 HListTest.scala
@@ -117,6 +117,10 @@ object HListTest
val (aa, bb) = ins7.i[_6].splitAt
val dropRight = x.reverse.i[_3].drop.reverse
+
+ val plain = 3 :: true :: 'k' :: HNil
+ val list: List[AnyVal] = toList(plain)
+ val list2 = toList[AnyVal](plain)
def run()
{
View
66 MList.scala
@@ -0,0 +1,66 @@
+import MList._
+
+import HList.{:: => :+: }
+import ~>._
+
+sealed trait MList[+M[_]] {
+
+ // For converting MList[Id] to an HList
+ // This is useful because type inference doesn't work well with Id
+ type Raw <: HList
+ def down(implicit ev: M ~> Id): Raw
+
+ // For natural transformations
+ type Map[N[_]] <: MList[N]
+ def map[N[_]](f: M ~> N): Map[N]
+
+ // convert to a regular List
+ def toList: List[M[_]]
+}
+final case class MCons[H, +T <: MList[M], +M[_]](head: M[H], tail: T) extends MList[M] {
+
+ type Raw = H :+: tail.Raw
+ def down(implicit f: M ~> Id): Raw = HCons(f(head), tail.down(f))
+
+ type Map[N[_]] = MCons[H, tail.Map[N], N]
+ def map[N[_]](f: M ~> N) = MCons( f(head), tail.map(f) )
+
+ // prepend
+ def :^: [N[X] >: M[X], G](g: N[G]): MCons[G, MCons[H, T, N], N] = MCons(g, this)
+
+ def toList = head :: tail.toList
+}
+sealed class MNil extends MList[Nothing] {
+
+ type Raw = HNil
+ def down(implicit f: Nothing ~> Id) = HNil
+
+ type Map[N[_]] = MNil
+ def map[N[_]](f: Nothing ~> N) = MNil
+
+ def :^: [M[_], H](h: M[H]): MCons[H, MNil, M] = MCons(h, this)
+
+ def toList = Nil
+}
+object MNil extends MNil
+
+object MList {
+ // nicer alias for pattern matching
+ val :^: = MCons
+}
+
+
+object MTest {
+
+ val f = new (Option ~> List) { def apply[T](o: Option[T]): List[T] = o.toList }
+
+ val x = Some(3) :^: Some("asdf") :^: MNil
+ val y = x map f
+ y match { case List(3) :^: List("asdf") :^: MNil => println("true") }
+
+ val head = new (List ~> Id) { def apply[T](xs: List[T]): T = xs.head }
+ // Id doesn't get inferred
+ val z = y.map[Id](head).down
+ // pattern matching with :^: without 'down' doesn't work (Id again)
+ z match { case 3 :+: "asdf" :+: HNil => println("true") }
+}
View
31 Transform.scala
@@ -0,0 +1,31 @@
+trait ~>[-A[_], +B[_]] {
+ def apply[T](a: A[T]): B[T]
+}
+
+object ~> {
+ type Id[X] = X
+ trait Const[A] { type Apply[B] = A }
+ implicit def idEq : Id ~> Id = new (Id ~> Id) { def apply[T](a: T): T = a }
+}
+
+trait Param[A[_], B[_]] {
+ type T
+ def in: A[T]
+ def ret(out: B[T])
+ def ret: B[T]
+}
+
+object Param {
+ implicit def pToT[A[_], B[_]](p: Param[A,B] => Unit): A~>B = new (A ~> B) {
+ def apply[s](a: A[s]): B[s] = {
+ val v: Param[A,B] { type T = s} = new Param[A,B] { type T = s
+ def in = a
+ private var r: B[T] = _
+ def ret(b: B[T]) {r = b}
+ def ret: B[T] = r
+ }
+ p(v)
+ v.ret
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.