JavaScriptでIota
Haskellはダメだったので、今度はJavaScriptでやってみる。
まず、関数iを定義する。
折り返して書いたけど、実際の構造はreturn f (function(x)...) (function(x)...);
function i(f){ return f(function(x){return function(y){return function(z){return x(z)(y(z));};};}) (function(x){return function(y){return x;};}); }
テストしてみる。
iにiを適用すると恒等関数になるはずなのでi(i)(0)は0を返すはず。
どうやら今回は成功。
js> i(i)(0) 0
基本関数を作る。
コメントはHaskell風の同等関数の定義(Haskellだと大文字の関数は作れないけど)
追記:見にくいけどその後ろに途中の計算をメモ
I = i(i); // I x = x K = i(i(I)); // K x y = x S = i(K); // S x y z = x z (y z) B = S(K(S))(K); // B x y z = x (y z) -- S(KS)Kxyz = KSx(Kx)yz = S(Kx)yz = Kxz(yz) = x(yz) D = B(B) // D w x y z = w x (y z) -- BBwxyz = B(wx)yz = wx(yz)
基本関数を使ってチャーチ数を移植する。
zero = K(I); // zero f x = x -- KIfx = Ix = x succ = S(B); // succ a f x = f (a f x) -- SBafx = Bf(af)x = f(afx) add = B(S)(D); // add a b f x = a f (b f x) -- BSDabfx = S(Da)bfx = Daf(bf)x = af(bfx) mul = B; // mul a b f = a (b f) pow = I; // pow a b = a b ←今回は手抜きによりaのb乗ではなくbのa乗 one = succ(zero); two = succ(one); three = succ(two);
検算用の10進数変換関数
function num(n){ return n(function(x){return x+1;})(0); }
実際に計算させてみる。
js> num(add(two)(three)) 5 js> num(mul(two)(three)) 6 js> num(pow(two)(three)) 9
ちゃんと動いてるようなので、I,K,S,B,Dをiで書き直す。
さすが難解言語。この瞬間にもう読めない。
zero = i(i(i(i)))(i(i)); succ = i(i(i(i(i))))(i(i(i(i(i))))(i(i(i(i)))(i(i(i(i(i))))))(i(i(i(i))))); add = i(i(i(i(i))))(i(i(i(i)))(i(i(i(i(i))))))(i(i(i(i))))(i(i(i(i(i)))))(i(i(i(i(i))))(i(i(i(i)))(i(i(i(i(i))))))(i(i(i(i))))(i(i(i(i(i))))(i(i(i(i)))(i(i(i(i(i))))))(i(i(i(i)))))); mul = i(i(i(i(i))))(i(i(i(i)))(i(i(i(i(i))))))(i(i(i(i)))); pow = i(i); one = succ(zero); two = succ(one); three = succ(two);
iだけを使ったバージョンで計算させてみる。
js> num(add(two)(three)) 5 js> num(mul(two)(three)) 6 js> num(pow(two)(three)) 9