Created
February 25, 2015 23:25
-
-
Save ceedubs/2b4e26796797594c08bc to your computer and use it in GitHub Desktop.
HStack and HDequeue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz._ | |
import shapeless._ | |
import shapeless.ops.hlist._ | |
/** contrived IndexedState example */ | |
object HStack extends App { | |
def push[H, T <: HList](h: H): IndexedState[T, H :: T, H] = | |
IndexedState(t => (h :: t, h)) | |
def pop[H, T <: HList]: IndexedState[H :: T, T, H] = | |
IndexedState(l => (l.tail, l.head)) | |
def peek[H, T <: HList]: IndexedState[H :: T, H :: T, H] = | |
IndexedState(l => (l, l.head)) | |
def app[L <: HList] = for { | |
_ <- push[Int, L](1) | |
_ <- push("foo") | |
foo <- pop | |
_ <- push(foo + "bar") | |
foobar <- peek | |
} yield foobar | |
println(app("baz" :: true :: 64L :: HNil)) | |
} | |
final case class HDequeue[L <: HList, R <: HList](l: L, r: R) | |
object HDequeue extends App { | |
def pushFront[A, L <: HList, R <: HList](a: A): IndexedState[HDequeue[L, R], HDequeue[A :: L, R], A] = | |
IndexedState(s1 => (HDequeue(a :: s1.l, s1.r), a)) | |
def pushBack[A, L <: HList, R <: HList](a: A): IndexedState[HDequeue[L, R], HDequeue[L, A :: R], A] = | |
IndexedState(s1 => (HDequeue(s1.l, a :: s1.r), a)) | |
def popFront[L <: HList, R <: HList](implicit p: PopFront[L, R]): IndexedState[HDequeue[L, R], p.DOut, p.A] = | |
IndexedState(p(_)) | |
def app[L <: HList, R <: HList] = for { | |
_ <- pushFront[Int, L, R](1) | |
foo <- pushBack("foo") | |
one <- popFront[Int :: L, String :: R] | |
} yield one | |
println(app(HDequeue("baz" :: true :: HNil, 64L :: HNil))) | |
println(popFront[HNil, Long :: HNil].apply(HDequeue(HNil, 64L :: HNil))) | |
} | |
sealed trait PopFront[L <: HList, R <: HList] { | |
type A | |
type LOut <: HList | |
type ROut <: HList | |
type DOut = HDequeue[LOut, ROut] | |
def apply(d: HDequeue[L, R]): (HDequeue[LOut, ROut], A) | |
} | |
sealed trait PopFrontInstances0 { | |
type Aux[L <: HList, R <: HList, _A, _LOut <: HList, _ROut <: HList] = PopFront[L, R] { | |
type A = _A | |
type LOut = _LOut | |
type ROut = _ROut | |
} | |
implicit def popFrontLeft[_A, LT <: HList, R <: HList]: Aux[_A :: LT, R, _A, LT, R] = | |
new PopFront[_A :: LT, R] { | |
type A = _A | |
type LOut = LT | |
type ROut = R | |
def apply(d: HDequeue[A :: LT, R]) = (HDequeue(d.l.tail, d.r), d.l.head) | |
} | |
} | |
object PopFront extends PopFrontInstances0 { | |
implicit def popFrontRight[_A, RT <: HList]: Aux[HNil, _A :: RT, _A, HNil, RT] = | |
new PopFront[HNil, _A :: RT] { | |
type A = _A | |
type LOut = HNil | |
type ROut = RT | |
def apply(d: HDequeue[HNil, _A :: RT]) = (HDequeue(HNil, d.r.tail), d.r.head) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment