最近、λ計算の基礎を教えているので、Common Lispに単純なλ計算エバリュエーターを実装しました。の正規形のY fac 3
正規次数削減を求めると、619ステップかかります。
もちろん、紙で同様の削減を行うたびに、型なしのλ計算を使用することはありませんでしたが、それらに作用する数と関数を追加しました。この場合、facは次のように定義されます。
fac = λfac.λn.if (= n 0) 1 (* n (fac (- n 1)))
この場合、考慮=
、*
および-
関数をカリー化など、それだけで取得するには、およそ50のステップを取るY fac 3
その正規形に6
。
しかし、私の評価者では、以下を使用しました。
true = λx.λy.x
false = λx.λy.y
⌜0⌝ = λf.λx.x
succ = λn.λf.λx.f n f x
⌜n+1⌝ = succ ⌜n⌝
zero? = λn.n (λx.false) true
mult = λm.λn.λf.m (n f)
pred = λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u)
fac = λfac.λn.(zero? n) ⌜1⌝ (* n (fac (pred n)))
Y = λf.(λf.λx.f (x x)) f ((λf.λx.f (x x)) f)
619ステップで、Y fac ⌜3⌝
の通常の形式⌜6⌝
、つまりに戻りλf.λx.f (f (f (f (f (f x)))))
ます。
多くのステップの簡単な概要から、それはpred
そのような長い削減を保証する定義だと思いますが、それでもそれが私の実装の大きな厄介なバグかもしれないのではないかと思っています...
編集:私は最初に1000ステップについて質問しましたが、そのうちのいくつかは実際に通常の順序の誤った実装を引き起こしたため、最初のステップ数の2/3になりました。以下にコメントするように、私の現在の実装では、ChurchからPeano演算に切り替えると、実際にはステップ数が増加します…