λ式の Combinatory Logic変換とその評価


λ式の構文ルール

E = \x.E | E1 E2 | V | C
V = 変数
C = 定数

Combinator Logic(CL)はS K Iコンビネータ。CLで計算を表現すると、束縛変数がなくなるのがいいところ。

λ式をCLに変換するルール

[]\x.E => [x]E
[](E1 E2) => []E1 []E2
[]v => v

[x]\y.E => [x]([y]E)
[x](E1 E2) => S [x]E1 [x]E2
[x]x => I
[x]v => K v
  : v = S, K, I, consts, freevars

CL評価ルール

[[S x y z]] => [[x z (y z)]]
[[K x y]] => [[y]]
[[I x]] => [[x]]
[[a b]] => [[[[a]] [[b]]]]
[[c]] => c
  : c = consts

λ式=>CL変換例

\x.\y.y x =>
[x](\y.y x) =>
[x]([y](y x)) =>
[x](S [y]y [y]x) =>
[x](S I (K x)) =>
[x](S I (K x)) =>
S [x](S I) [x](K x) =>
S (S [x]S [x]I) (S [x]K [x]x) =>
S (S (K S) (K I)) (S (K K) I)

CL評価例

[(\x.\y.y x) z s ==> s z]

S (S (K S) (K I)) (S (K K) I) z s =>
(S (K S) (K I)) z (S (K K) I z) s =>
(K S) z (K I z) (S (K K) I z) s =>
S (K I z) (S (K K) I z) s =>
(K I z) s (S (K K) I z s) =>
I s (S (K K) I z s) =>
s (S (K K) I z s) =>
s ((K K) z (I z) s) =>
s (K (I z) s) =>
s (I z) =>
s z

Haskellコード

data Term = Lam String Term | App Term Term | Var String | Con String
  deriving Show
data Comb = Comb `P` Comb | S | K | I | V String | C String
  deriving (Show, Eq)

toCL (Lam n body) = trans n body
toCL (App opr opd) = (toCL opr) `P` (toCL opd)
toCL (Var x) = (V x)
toCL (Con v) = (C v)

trans p (Lam n body) = trans2 p (trans n body)
trans p (App opr opd) = S `P` (trans p opr) `P` (trans p opd)
trans p (Var x) | p == x = I
trans p (Var x) = K `P` (V x)
trans p (Con v) = K `P` (C v)

trans2 p (a `P` b) = S `P` (trans2 p a) `P` (trans2 p b)
trans2 p (V x) | p == x = I
trans2 p a = K `P` a

eval (S `P` x `P` y `P` z) = eval (x `P` z `P` (y `P` z))
eval (K `P` x `P` y) = eval x
eval (I `P` x) = eval x
eval (a `P` b) = let na = eval a in
                 let nb = eval b in
                 if a /= na || b /= nb then eval (na `P` nb) else (a `P` b)
eval a = a

-- toCL (Lam "x" (Lam "y" (App (Var "y") (Var "x"))))
-- eval ((toCL (Lam "x" (Lam "y" (App (Var "y") (Var "x"))))) `P` (C "zero") `P` (C "succ"))

実行例

$ ghci combinatory.hs
GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( combinatory.hs, interpreted )
Ok, modules loaded: Main.
*Main> toCL (Lam "x" (Lam "y" (App (Var "y") (Var "x"))))
(S `P` ((S `P` (K `P` S)) `P` (K `P` I))) `P` ((S `P` (K `P` K)) `P` I)
*Main> eval ((toCL (Lam "x" (Lam "y" (App (Var "y") (Var "x"))))) `P` (C "zero") `P` (C "succ"))
C "succ" `P` C "zero"
*Main>