The Continuation Monad(継続モナド)
The monad of continuations given here is a straightforward adaptation of Phil Wadler's paper "The Essence of Functional Programming" (1992).
ここでの継続モナドはPhil Wadlerの論文「The Essence of Functional Programming」(1992)の素直な適用です。
I call instances of M "monadic artifacts", or just artifacts.
Mのインスタンスを「モナド成果物」もしくは単に成果物と呼びます。
They are values (hence Scala objects), which can be passed around and bound or decomposed.
それらは値であり(ゆえにScalaオブジェクトであり)、それらは次々に渡され、バインドされるか分解されるでしょう。
文章はこれで終わりで、あとサンプルコードがある。
でもまだモナドはなんとなくもわからない。
これからも知識の蓄積と熟成を繰り返さないと、マスターは遠いな。
object Main { //type Cont[A] = (A => Unit) => Unit; /** a class for "monadic artifacts" */ case class M[+A](in: (A=>Any)=>Any) { def map[B](f: A => B) = bind(this, {x: A => unit(f(x))}); def flatMap[B](f: A => M[B]) = bind(this, f); } def unit[A](x:A) = M(k:(A=>Any) => k(x)); def bind[A,B](m:M[A], f:A=>M[B]):M[B] = M(k => m.in (x => f(x).in(k))); def callCC[A](e:(A=>M[A])=>M[A]):M[A] = M(k => e(a => M(ignored => k(a))).in(k)); // Michel's Explanation: // The argument given to "e" must be a reified continuation, i.e. // a function which, when invoked with some parameter, replaces // the current continuation with the one of the call to callCC. In // the code above, "ignored" is the current continuation, and "k" // is the one of the call to callCC. Finally, "a" is the value // which will be "returned" by the call to callCC. // We also have to give a continuation to the whole callCC // expression, because it is perfectly possible that the reified // continuation is never invoked. This continuation is "k", quite // naturally. We therefore pass it to e's "input". // the "final continuation" def show[A]():(A)=>Unit = {x:A => Console.println(x)} // convenience def show[A](m:M[A]):Unit = { m.in (show()) } // convenience^2 def showshow[A](m:M[M[A]]):Unit = { m.in (k => k.in (show())) } def reverse(s:String):String = { val sb = new StringBuffer(); var i = s.length(); while(i > 0) { i = i - 1; sb.append(s.charAt(i)); } sb.toString(); } def main(args:Array[String]): Unit = { // example 1 val p = unit[Int](3); // computation that simply returns 3 Console.println("example 1 (unit)"); show(p); // same as `p.in (show())' Console.println("---"); // example 2a val m = unit[String]("42"); // result of Deep Thought val f = {x:String => M(k:(String=>Any) => k("meaning of life:"+x))}; val n = bind(m, f); Console.println("example 2a (bind)"); show(n); // same as `n.in (show())' Console.println("---"); // example 2b (same as 2a, but with convenient syntax) val _n2 = for(val x <- unit("42"); val n <- M(k:(String=>Any) => k("meaning of life:"+x))) yield n; Console.println("example 2b (bind, nice syntax)"); show(_n2); // same as `_n2.in (show())' Console.println("---"); // example 3 val _r = for(val x <- n; val m <- unit(reverse(x))) yield m; // same as `val _r = bind(n, {x:String => unit(reverse(x))})' Console.println("example 3 (composition)"); show(_r); //same as `_r.in (show())' Console.println("---"); // example 4 def meaning(_x:M[String]=>M[M[String]]):M[M[String]] = { bind(unit(unit("42")), _x) } val someComputation = meaning({x => unit(bind(x, {z:String => unit("the meaning of life is "+z)}))}); Console.println("example 4 (why callCC matters)"); showshow( someComputation ) ; //.in {k => k.in (show())}; showshow( callCC(meaning) ) // look Ma, no scheme! } }