Created
September 3, 2011 14:00
-
-
Save halcat0x15a/1191224 to your computer and use it in GitHub Desktop.
ScalazでIteratee
This file contains 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
sealed trait StreamG[+E] | |
case class Empty[E]() extends StreamG[E] | |
case class El[E](el: E) extends StreamG[E] | |
case class EOF[E]() extends StreamG[E] | |
sealed trait IterV[+E, +A] | |
case class Done[E, A](x: A, str: StreamG[E]) extends IterV[E, A] | |
case class Cont[E, A](k: StreamG[E] => IterV[E, A]) extends IterV[E, A] |
This file contains 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
def enum[E, A]: (IterV[E, A], List[E]) => IterV[E, A] = { | |
case (i, Nil) => i | |
case (i@Done(_, _), _) => i | |
case (Cont(k), x :: xs) => enum(k(El(x)), xs) | |
} | |
def run[E, A]: IterV[E, A] => Option[A] = { | |
case Done(x: A, _) => Some(x) | |
case Cont(k) => k(EOF()) match { | |
case Done(x: A, _) => Some(x) | |
case _ => None | |
} | |
} |
This file contains 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
def head[E]: IterV[E, Option[E]] = { | |
def step: StreamG[E] => IterV[E, Option[E]] = { | |
case El(el: E) => Done(Some(el), Empty()) | |
case Empty() => Cont(step) | |
case EOF() => Done(None, EOF()) | |
} | |
Cont(step) | |
} | |
def peek[E]: IterV[E, Option[E]] = { | |
def step: StreamG[E] => IterV[E, Option[E]] = { | |
case c@El(el: E) => Done(Some(el), c) | |
case Empty() => Cont(step) | |
case EOF() => Done(None, EOF()) | |
} | |
Cont(step) | |
} | |
def drop[E]: Int => IterV[E, Unit] = { | |
case 0 => Done((), Empty()) | |
case n => { | |
def step: StreamG[E] => IterV[E, Unit] = { | |
case El(_) => drop(n - 1) | |
case Empty() => Cont(step) | |
case EOF() => Done((), EOF()) | |
} | |
Cont(step) | |
} | |
} | |
def length[E]: IterV[E, Int] = { | |
def step: (Int, StreamG[E]) => IterV[E, Int] = { | |
case (acc, El(_)) => Cont(step.curried(acc + 1)) | |
case (acc, Empty()) => Cont(step.curried(acc)) | |
case (acc, EOF()) => Done(acc, EOF()) | |
} | |
Cont(step.curried(0)) | |
} |
This file contains 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
implicit def IterVMonad[E] = new Monad[({type X[A] = IterV[E, A]})#X] { | |
def pure[A](x: => A): IterV[E, A] = Done(x, Empty()) | |
def bind[A, B](m: IterV[E, A], f: A => IterV[E, B]): IterV[E, B] = m match { | |
case Done(x: A, str: StreamG[E]) => f(x) match { | |
case Done(x: B, _) => Done(x, str) | |
case Cont(k) => k(str) | |
} | |
case Cont(k) => Cont((str: StreamG[E]) => bind(k(str), f)) | |
} | |
} |
This file contains 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
def f[E](l: List[E]) = run(enum(drop(2) >|> length, l)) | |
f(List(1, 2, 3)) assert_=== Some(1) | |
f(List(1, 2, 3, 4, 5)) assert_=== Some(3) | |
f(List(1)) assert_=== Some(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment