疑似Continuationモナド
HaskellのContinuationモナドを雰囲気だけGaucheに移植してみる。
Contクラス
まず、疑似Continuationモナドとして、Contクラスを作る。
Contクラスが持つrunContスロットは同名のgetter関数を持つ。
returnは全然ジェネリックファンクションになってないんだけど、>>=と横並びにしたかったので。
(define-class <Cont> () ((runCont :init-keyword :r :getter runCont))) (define-method return (a) (make <Cont> :r (lambda (k) (k a)))) (define-method >>= ((c <Cont>) f) (make <Cont> :r (lambda (k) ((runCont c) (lambda (a) ((runCont (f a)) k))))))
対応するHaskellのコード
newtype Cont r a = Cont { runCont :: ((a -> r) -> r) } instance Monad (Cont r) where return a = Cont $ \k -> k a c >>= f = Cont $ \k -> runCont c (\a -> runCont (f a) k)
階乗のサンプル
上記を使って階乗を書いてみる。
(define (fact n) (if (eq? n 0) (return 1) (>>= (fact (- n 1)) (lambda (a) (return (* n a)))))) (define (main args) ((runCont (fact 4)) print))
対応するHaskellのコード(この間書いたdo記法にする直前版)
fact 0 = return 1 fact n = (fact $ n - 1) >>= (\a -> return $ n * a) main = runCont (fact 4) print
まあ、要するにrunContは単なるContクラスのgetterでしかない、というのを実感したかっただけ。