Arrow はスタック言語だと口で言うだけじゃ信用してもらえないと思うので軽く作ってみる。
もしかして、Haskell で Joy (風言語)というのはとても難しいのではと思っていた。何故難しいかというと、スタックというのはリストなのだけど、リストというのは普通一つの型しか入れる事が出来ないのだ。でもリストじゃなくてタプルだったら問題ないと気が付いたのでやってみた。どちらかと言うと Cat 言語にあわせて作りました。サボってパーサーを作ってないので、文法は Arrow のままです。こんな風に実行します。リストの最後に factorial の Cat 風定義も置いておきました。
Cat> runCat $ push 3 >>> push 4 >>> add (7,())
module Cat where import Control.Arrow data Quoation a = Q a instance Show (Quoation a) where showsPrec _ (Q a) = showString "_q_" push x st = (x, st) -- Cat primitives Level0 inc (x, xs) = (x + 1, xs) pop :: (a, b) -> b pop (x, st) = st dup (x, st) = (x, (x, st)) dip (q, (x, st)) = (x, (apply (q, st))) swap (x1, (x2, st)) = (x2, (x1, st)) apply (Q q, st) = q st -- if branch (f, (t, (True, st))) = apply (t, st) branch (f, (t, (False, st))) = apply (f, st) -- Cat primitives Level1 dec (x, xs) = (x - 1, xs) -- Cat primitives Level3 mul (x1, (x2, xs)) = (x1 * x2, xs) add (x1, (x2, xs)) = (x1 + x2, xs) lt (x1, (x2, xs)) = (x1 > x2, xs) -- Useful functions pushQ q st = push (Q q) st runCat f = f () -- define rec_fac { dup 1 < [pop 1] [dup dec rec_fac *] if } -- DEFINE fact == dup 1 < [pop 1] [dup pred fact *] branch. fact :: (Integer, a) -> (Integer, a) fact = dup >>> push 1 >>> lt >>> pushQ (pop >>> push 1) >>> pushQ(dup >>> dec >>> fact >>> mul) >>> branch -- Main> runCat $ push 10 >>> fact -- (3628800,())