2011-12-22
Scala で Iteratee と Enumerator を書く練習
とりあえず使い方だけメモ
package com.github.cooldaemon.scalaz_test
import scalaz._
object TryIteratee {
import Scalaz._
import IterV._
def run {
implicit val ListEnum = new Enumerator[Seq] {
def apply[E, A](e: Seq[E], i: IterV[E, A]): IterV[E, A] = {
e match {
case Seq() => i
case x::xs => i.fold(
done = (_, _) => i,
cont = k => apply(xs, k(El(x)))
)
}
}
}
implicit val StreamEnum = new Enumerator[Stream] {
def apply[E, A](e: Stream[E], i: IterV[E, A]): IterV[E, A] = {
e match {
case Stream() => i
case x #:: xs => i.fold(
done = (_, _) => i,
cont = k => apply(xs, k(El(x)))
)
}
}
}
val seq = Seq.range(1, 5)
head(seq).run assert_=== Some(1)
val m = for {
x <- head[Int]
y <- head[Int]
} yield (x, y)
m(seq).run assert_=== (Some(1), Some(2))
def dropAndPrintAll[E] :IterV[E, Unit] = {
def step(s: Input[E]) :IterV[E, Unit] = {
s(
el = {e =>
println(e)
Cont(step)
},
empty = Cont(step),
eof = Done((), EOF[E])
)
}
Cont(step)
}
println("--<自作 Iteratee>--")
dropAndPrintAll(seq).run
def peekAndPrintAll[E] :IterV[E, Unit] = {
def step(initS: Input[E])(s: Input[E]): IterV[E, Unit] = {
s(
el = {e =>
println(e)
Cont(step(initS))
},
empty = Cont(step(initS)),
eof = Done((), initS)
)
}
Cont({s => step(s)(s)})
}
val m2 = for {
_ <- peekAndPrintAll[Int]
x <- head[Int]
} yield x
println("--<Iteratee の合成>--")
m2(seq).run assert_=== Some(1)
println("--<Enumerator を後から追加>--")
val m3 = dropAndPrintAll(seq)
val m4 = m3(Stream.range(5, 10)) // Seq に Stream を追加しても良い
m4.run
}
}
解説は後で。例とは言え Iteratee の中に副作用が存在する所がダサい。
疑問点その1
下記を末尾再帰にするには…
def apply[E, A](e: Seq[E], i: IterV[E, A]): IterV[E, A] = { e match { case Seq() => i case x::xs => i.fold( done = (_, _) => i, cont = k => apply(xs, k(El(x))) ) } }
下記のようにする必要がある。何でだろー?
@annotation.tailrec def apply[E, A](e: Seq[E], i: IterV[E, A]): IterV[E, A] = {
val next: Option[(Seq[E], IterV[E, A])] = e match {
case Seq() => None
case x::xs => i.fold(
done = (_, _) => None,
cont = k => some((xs, k(El(x))))
)
}
next match {
case None => i
case Some((es, is)) => apply(es, is)
}
}
疑問点その2
Haskell みたいに Enumerator 同士を合成する方法が解らない
参考
トラックバック - http://d.hatena.ne.jp/cooldaemon/20111222/1324527791
リンク元
- 364 http://search.yahoo.co.jp/search?p=edoc 使い方&rs=2&ei=UTF-8&fr=slv1-dyzce5
- 357 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCkQFjAA&url=http://d.hatena.ne.jp/cooldaemon/20070806/1186385908&ei=KjsnT_3cH4GImQWs4JS4Aw&usg=AFQjCNG1eQFkZZegIZyHpvjsOzqpRufySw
- 250 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CDcQFjAB&url=http://d.hatena.ne.jp/cooldaemon/20080702/1214928860&ei=oRk6T9fqOK7imAWXxcHTCg&usg=AFQjCNGqy2irCYF7ENJ3i8zcX_QHOFApmA&sig2=Twzaz_WB-zKP7r1Xqg5kPA
- 138 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0CDsQFjAC&url=http://d.hatena.ne.jp/cooldaemon/20110107/1294388914&ei=tH0uT6iOJOPMmAXo88HIDw&usg=AFQjCNF9pm_-3HdKDcXPTFv4jJDvwhaJ_w&sig2=Bvp8A74NlF4wQVdwyTUu3g
- 110 http://www.google.co.jp/url?sa=t&rct=j&q=git svn branch&source=web&cd=1&ved=0CCoQFjAA&url=http://d.hatena.ne.jp/cooldaemon/20080702/1214928860&ei=wL7yTtPvNcaMmQXB3_y7Ag&usg=AFQjCNGqy2irCYF7ENJ3i8zcX_QHOFApmA&sig2=iv1TdEEzf-C9lKYNTJ4row
- 90 https://www.google.co.jp/
- 86 http://blog.blueblack.net/item_164
- 86 http://d.hatena.ne.jp/rdera/20090113/1231819016
- 77 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cts=1330827632811&ved=0CHUQFjAD&url=http://d.hatena.ne.jp/cooldaemon/20070609/1181403184&ei=UtFST8KIN6SImQWV3Nm2Ag&usg=AFQjCNG_-7Ze3Kfn7L304oS4ep2h-2NJ8w&sig2=eRlq2OY9kPOaEPrI4Tb
- 66 http://longurl.org