Como tenho ensinado as bases do cálculo λ ultimamente, implementei um avaliador simples do cálculo λ no Common Lisp. Quando pergunto a forma Y fac 3
normal de redução na ordem normal, são necessários 619 passos, o que parecia um pouco demais.
Obviamente, toda vez que fazia reduções semelhantes no papel, nunca usava o cálculo λ não tipado, mas adicionava números e funções operando neles. Nesse caso, fac é definido como tal:
fac = λfac.λn.if (= n 0) 1 (* n (fac (- n 1)))
Neste caso, considerando-se =
, *
e -
como currying funções, só demorar cerca de 50 passos para chegar Y fac 3
à sua forma normal 6
.
Mas no meu avaliador, usei o seguinte:
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)
Em 619 etapas, chego Y fac ⌜3⌝
à forma normal de ⌜6⌝
, a saber λf.λx.f (f (f (f (f (f x)))))
.
A partir de uma rápida verificação das muitas etapas, acho que é a definição pred
que justifica uma redução tão longa, mas ainda me pergunto se isso pode ser um grande bug desagradável na minha implementação ...
EDIT: Inicialmente, perguntei cerca de mil etapas, algumas das quais realmente causaram uma implementação incorreta da ordem normal, então reduzi para 2/3 do número inicial de etapas. Como comentado abaixo, com minha implementação atual, a mudança da aritmética da Igreja para a Peano realmente aumenta o número de etapas…
fonte
Y
parece crucial aqui (especialmente para números Peano) para obter reduções curtas.Se eu pensar em quantas coisas uma CPU faz para calcular o fatorial de 3, digamos em Python, então algumas centenas de reduções não são um grande problema.
fonte