Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Created June 14, 2014 21:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save djspiewak/f4ac177199cf3c6660bd to your computer and use it in GitHub Desktop.
Save djspiewak/f4ac177199cf3c6660bd to your computer and use it in GitHub Desktop.
package com.codecommit.misc
import scalaz._
import scalaz.concurrent.Task
import scalaz.iteratee._
import scalaz.stream._
object conversion {
// TODO generalize to EmitterT
type Emitter[A, E] = Free[({ type ?[+?] = (?, Option[E]) })#?, A]
// functor for emitter
implicit def optPairFunctor[E]: Applicative[({ type ?[?] = (?, Option[E]) })#?] = new Applicative[({ type ?[?] = (?, Option[E]) })#?] {
def point[A](a: => A): (A, Option[E]) = (a, None)
override def map[A, B](fa: (A, Option[E]))(f: A => B): (B, Option[E]) = {
val (a, opt) = fa
(f(a), opt)
}
def ap[A, B](fa: => (A, Option[E]))(f: => (A => B, Option[E])): (B, Option[E]) = {
// TODO generalize E to List[E], which seems intuitive
val (a, _) = fa
val (trans, opt) = f
(trans(a), opt)
}
}
implicit def trampolineInstance[E]: Monad[({ type ?[?] = Emitter[?, E] })#?] = {
new Monad[({ type ?[?] = Emitter[?, E] })#?] {
def point[A](a: => A) = Free.return_[({ type ?[+?] = (?, Option[E]) })#?, A](a)
def bind[A, B](ta: Emitter[A, E])(f: A => Emitter[B, E]) = ta flatMap f
}
}
def iteratee[E]: StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit] = {
StepT.Cont[E, ({ type ?[?] = Emitter[?, E] })#?, Unit] { in =>
val back: Emitter[StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit], E] = in.fold[Emitter[StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit], E]](
el = { e => liftF[({ type ?[+?] = (?, Option[E]) })#?, StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit]]((iteratee[E], Some(e))) },
empty = liftF[({ type ?[+?] = (?, Option[E]) })#?, StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit]]((iteratee[E], None)),
eof = liftF[({ type ?[+?] = (?, Option[E]) })#?, StepT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit]]((StepT.Done[E, ({ type ?[?] = Emitter[?, E] })#?, Unit]((), in), None)))
IterateeT.iterateeT[E, ({ type ?[?] = Emitter[?, E] })#?, Unit](back)
}
}
// so much useful stuff in 7.1...
def liftF[S[+_], A](value: => S[A])(implicit S: Functor[S]): Free[S, A] =
Free.Suspend(S.map(value)(Free.Return[S, A]))
def convert[E](enum: (({ type ?[?] = StepT[E, ({ type ?[?] = Emitter[?, E] })#?, ?] })#? ~> ({ type ?[?] = IterateeT[E, ({ type ?[?] = Emitter[?, E] })#?, ?] })#?)): Process[Task, E] = {
def handle(emit: Emitter[Unit, E]): Option[(E, Emitter[Unit, E])] = {
emit.resume match {
case \/-(_) => None
case -\/((emit2, Some(value))) => Some((value, emit2))
case -\/((emit2, None)) => handle(emit2)
}
}
Process.unfold[Emitter[Unit, E], E](enum(iteratee[E]).run)(handle)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment