昨日の Haskell 版 Unlambda を Scala で書いてみた
久しぶりに Scala ネタ。
ほぼ、昨日のまんま。やっぱり .x, r, s, k, i だけ。
object Unlambda { abstract class Tree[T] case class Leaf[T](elm:T) extends Tree[T] case class Branch[T](l:Tree[T], r:Tree[T]) extends Tree[T] class Func(f:Func => Func) { def apply(g:Func):Func = f(g) } def p(c:Char):Func = new Func((f) => {print(c); f}) val r:Func = p('\n') val s:Func = new Func((f) => new Func((g) => new Func((h) => (f(h))(g(h))))) val k:Func = new Func((f) => new Func((g) => f)) val i:Func = new Func((f) => f) def parse(cs:List[Char]):Tree[Func] = { def parse_aux(cs:List[Char]):Option[(Tree[Func], List[Char])] = cs match { case '`'::cs => parse_aux(cs).flatMap((p) => p match { case (l, cs) => parse_aux(cs).flatMap((p) => p match { case (r, cs) => Some((Branch(l, r), cs)) }) }) case '.'::c::cs => Some((Leaf(p(c)), cs)) case 'r'::cs => Some((Leaf(r), cs)) case 's'::cs => Some((Leaf(s), cs)) case 'k'::cs => Some((Leaf(k), cs)) case 'i'::cs => Some((Leaf(i), cs)) case c::cs if (c.isWhitespace) => parse_aux(cs) case _ => None } parse_aux(cs) match { case Some((t, Nil)) => t case Some((t, rest)) if (rest.forall(_.isWhitespace)) => t case _ => throw new RuntimeException } } def eval(t:Tree[Func]):Func = t match { case Leaf(f) => f case Branch(l, r) => (eval(l))(eval(r)) } def main(args:Array[String]) { eval(parse(scala.io.Source.fromFile(args(0)).toList)) } }
相変わらず、ファイル入出力が分かりません。だれかイディオムでもまとめてないかしら。
追記 2010-09-07
Monadについて - NoisySpot/メモ帳 を読んで、ふとこの Unlambda サブセットのことを思い出したので、誰か教えてくれないかなー、と、ちょっと呟いてみた。
2人もお返事くれました。
Haskell の do 構文とほとんど同じノリですね。