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