Est-ce que quelques centaines d'étapes de réduction sont trop nombreuses pour obtenir la forme normale de Y fac ⌜3⌝?

9

Comme j'ai récemment enseigné les bases du λ-calcul, j'ai implémenté un évaluateur de λ-calcul simple en Common Lisp. Lorsque je demande la forme Y fac 3normale de réduction dans l'ordre normal, cela prend 619 étapes, ce qui semblait un peu trop.

Bien sûr, chaque fois que je faisais des réductions similaires sur du papier, je n'utilisais jamais le λ-calcul non typé, mais j'y ajoutais des nombres et des fonctions. Dans ce cas, fac est défini comme tel:

fac = λfac.λn.if (= n 0) 1 (* n (fac (- n 1)))

Dans ce cas, compte tenu =, *et -que les fonctions taitement, il prend seulement environ 50 étapes pour obtenir Y fac 3sa forme normale 6.

Mais dans mon évaluateur, j'ai utilisé ce qui suit:

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)

En 619 étapes, je passe Y fac ⌜3⌝à la forme normale de ⌜6⌝, à savoir λf.λx.f (f (f (f (f (f x))))).

D'après un survol rapide des nombreuses étapes, je suppose que c'est la définition predqui justifie une réduction si longue, mais je me demande toujours si ce n'est peut-être qu'un gros bogue méchant dans mon implémentation ...

EDIT: J'ai d'abord demandé environ un millier d'étapes, dont certaines ont en effet causé une mauvaise mise en œuvre de l'ordre normal, donc je suis descendu aux 2/3 du nombre initial d'étapes. Comme indiqué ci-dessous, avec mon implémentation actuelle, le passage de l'arithmétique Church à Peano augmente en fait le nombre d'étapes…

Nulle part homme
la source

Réponses:

11

Le codage d'église est vraiment mauvais si vous voulez l'utiliser pred. Je vous conseille d'utiliser un codage plus efficace dans le style Peano:

// arithmétique

: p_zero = λs.λz.z
: p_one = λs.λz.s p_zero
: p_succ = λn.λs.λz.sn
: p_null = λn.n (λx. ff) tt
: p_pred = λn.n (λp.p) p_zero
: p_plus = μ! f.λn.λm.n (λp. p_succ (! fpm)) m
: p_subs = μ! f.λn.λm.n (λp. p_pred (! fpm)) m
: p_eq = μ! f.λm.λn. m (λp. n (λq.! fpq) ff) (n (λx.ff) tt)
: p_mult = μ! f.λm.λn. m (λp. p_plus n (! fpn)) p_zero
: p_exp = μ! f.λm.λn. m (λp. p_mult n (! fpn)) p_one
: p_even = μ! f.λm. m (λp. pas (! fp)) tt

// Nombres

: p_0 = λs.λz.z
: p_1 = λs.λz.s p_0
: p_2 = λs.λz.s p_1
: p_3 = λs.λz.s p_2
...

Il s'agit d'un code extrait d'une de mes anciennes bibliothèques, et μ!f. …n'était qu'une construction optimisée pour Y (λf. …). (Et tt, ff, notsont booléens.)

Je ne suis pas vraiment sûr que vous obtiendriez de meilleurs résultats fac.

Stéphane Gimenez
la source
Merci pour l'astuce, travailler avec cet encodage alternatif m'a aidé à trouver quelques bugs dans mon implémentation. En fait, cela n'aide pas pour le nombre d'étapes, car après correction, retrouver la forme normale de 3! fait 619 pas avec les chiffres de l'Église et 687 avec les chiffres de Peano…
Nowhere man
Oui, c'est ce que je pensais, car l'utilisation d'une règle de réduction spéciale pour Ysemble cruciale ici (en particulier pour les nombres Peano) pour obtenir de courtes réductions.
Stéphane Gimenez
Juste curieux, qu'en est-il de 4 !, 5 !, 6! ?
Stéphane Gimenez
1
Curieusement, après 3 !, l'encodage Peano devient plus efficace que l'encodage Church. Pour obtenir la forme normale de respectivement 1 !, 2 !, 3 !, 4! et 5! avec Peano / Church, il faut 10/10, 40/33, 157/134, 685/667, 3541/3956 et 21629/27311 pas. Approximation du nombre d'étapes pour 6! par interpolation à partir des données précédentes est laissé comme un exercice pour le lecteur.
Nowhere man
1
Il semble que ce qui précède soit précisément les chiffres de Scott "Peano + λ = Scott". Quelque chose d'autre qui mériterait d'être essayé est leurs variantes binaires (à la fois pour Church et <strike> Peano </strike> Scott).
Stéphane Gimenez
2

Si je pense au nombre de choses qu'un processeur fait pour calculer la factorielle de 3, par exemple en Python, alors quelques centaines de réductions ne sont pas du tout un problème.

Andrej Bauer
la source