チャーチ数
チャーチ数を使うとλを使って自然数を表すことができます。詳しくは、ラムダ計算ABCを参照してください。
で。以下の関数curried_lambdaを使うと、
def curried_lambda(n = -1, xs = [], &f) n = f.arity if n < 0 if n == 0 f[*xs] else lambda {|x| curried_lambda(n - 1, xs + [x], &f) } end end
0〜3はこのように表現できます。
zero = curried_lambda {|f, x| x } # λfx.x one = curried_lambda {|f, x| f[x] } # λfx.fx two = curried_lambda {|f, x| f[f[x]] } # λfx.f(fx) three = curried_lambda {|f, x| f[f[f[x]]] } # λfx.f(f(fx))
つまりfを畳み込んだ回数が数です。一般化すると以下のようになります。
def n(m) curried_lambda do |f, x| (1 .. m).inject(x) {|a, i| f[a] } end end
このチャーチ数に演算を定義してます。
class Proc def to_i self[lambda {|n| n + 1 }][0] end def +(other) # λabfx.af(bfx) curried_lambda {|f, x| self[f][other[f][x]] } end def *(other) # λabf.a(bf) curried_lambda {|f| self[other[f]] } end def **(other) # λab.ba other[self] end end p n(100).to_i # => 100 p (n(2) + n(3)).to_i # => 5 p (n(2) * n(3)).to_i # => 6 p (n(2) ** n(3)).to_i # => 8
んー、すばらしいです。これ何てRuby?
参照: Ruby チャーチ数 - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。 - subtech