疑似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でしかない、というのを実感したかっただけ。