Skip to content

Instantly share code, notes, and snippets.

@ttim
Last active June 12, 2017 06:49
Show Gist options
  • Save ttim/4422fc15c60ea9a869555cbd3a9fa72d to your computer and use it in GitHub Desktop.
Save ttim/4422fc15c60ea9a869555cbd3a9fa72d to your computer and use it in GitHub Desktop.
case class M[A](value: A, list: List[String]) {
def flatMap[B](f: A => M[B]): M[B] = {
f(value) match {
case M(value2, list2) => M(value2, list ++ list2)
}
}
def map[B](f: A => B): M[B] = M(f(value), list)
}
def pureM[A](a: A): M[A] = M(a, List())
def write(s: String): M[Unit] = M((), List(s))
case class CF[A](value: M[Either[A, CF[A]]]) {
def unwrap: M[A] = value.flatMap[A] {
case Left(left: A) => pureM[A](left)
case Right(right: CF[A]) => right.unwrap
}
def flatMap[B](f: A => CF[B]): CF[B] = CF(value.flatMap[Either[B, CF[B]]] {
case Left(left: A) => f(left).value
case Right(right: CF[A]) => pureM(Right(right.flatMap(f)))
})
def map[B](f: A => B): CF[B] = flatMap(a => pure(f(a)))
}
def pure[A](a: A): CF[A] = CF(pureM(Left(a)))
def yielded[A](a: CF[A]): CF[A] = CF(pureM(Right(a)))
def lift[A](a: M[A]): CF[A] = CF(a.map(Left(_)))
def yieldC: CF[Unit] = yielded(pure[Unit]( () ))
def interleave[A, B](c1: CF[A], c2: CF[B]): M[(A, B)] = c1.value.flatMap[(A, B)] {
case Left(valueA: A) => c2.unwrap.map(valueB => (valueA, valueB))
case Right(valueB: CF[A]) => interleave[B, A](c2, valueB).map(p => (p._2, p._1))
}
val r1 = for {
x <- lift(write("1"))
y <- lift(write("2"))
_ <- yieldC
z <- lift(write("3"))
} yield 1
val r2 = for {
x <- lift(write("4"))
_ <- yieldC
y <- lift(write("5"))
} yield 2
println(interleave(r1, r2))
val test = pure(1)
println(test == test.map(identity))
println(yieldC == yieldC.map(identity))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment