Skip to content

Instantly share code, notes, and snippets.

@mariusdanciu
Last active December 17, 2015 17:49
Show Gist options
  • Save mariusdanciu/5649251 to your computer and use it in GitHub Desktop.
Save mariusdanciu/5649251 to your computer and use it in GitHub Desktop.
Iteratee
package net
object Main extends App {
import Iteratee._
val l = Enumerator.traverse(List[Input[Int]](Data(4), Data(5), EOF))(Iteratee.fold(1) {
case (a, e) => a * e
})
println(l)
}
sealed trait Input[+T]
case class Data[+T](t: T) extends Input[T]
case object EOF extends Input[Nothing]
sealed trait State[I, +O]
case class Cont[I, +O](f: I => Iteratee[I, O]) extends State[I, O]
case class Done[I, +O](t: O, rest: I) extends State[I, O]
case class Err[I](t: Throwable, rest: I) extends State[I, Nothing]
trait Iteratee[I, +O] {
def fold[R](f: (State[I, O] => R)): R
}
object Iteratee {
def apply[I, O](state: State[I, O]): Iteratee[I, O] = new Iteratee[I, O] {
def fold[R](f: (State[I, O] => R)): R = f(state)
override def toString = state toString
}
def fold[I, O](o: O)(f: ((O, I)) => O): Iteratee[Input[I], O] = {
def step(out: O)(in: Input[I]): Iteratee[Input[I], O] = in match {
case Data(t) => Iteratee(Cont(step(f((out, t)))))
case EOF => Iteratee(Done(out, in))
}
Iteratee(Cont(step(o)))
}
}
trait Enumerator[I] {
def apply[O](it: Iteratee[I, O]): Iteratee[I, O]
}
object Enumerator {
def traverse[I](in: Traversable[I]): Enumerator[I] = new Enumerator[I] {
def apply[O](it: Iteratee[I, O]): Iteratee[I, O] = {
(it /: in) {
case (a, i) => a.fold {
case Cont(f) => f(i)
case other => Iteratee(other)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment