Ok, entonces la idea de Números de la Iglesia es codificar "datos" usando funciones, ¿verdad? La forma en que funciona es mediante la representación de un valor mediante alguna operación genérica que realizaría con él. Por lo tanto, podemos ir en la otra dirección, lo que a veces puede aclarar las cosas.
Los numerales de las iglesias son una representación unaria de los números naturales. Entonces, usemos Z
para significar cero y Sn
para representar al sucesor de n
. Ahora podemos contar de esta manera: Z
, SZ
, SSZ
, SSSZ
... El número equivalente Iglesia toma dos argumentos - la primera corresponde a S
, y la segunda a Z
--¡entonces los utiliza para construir el patrón anterior. Así que da argumentos f
y x
, podemos contar de esta manera: x
, f x
, f (f x)
, f (f (f x))
...
Veamos lo que hace PRED.
En primer lugar, se crea un lambda teniendo tres arguments-- n
está el numeral Iglesia cuyo predecesor que queremos, por supuesto, lo que significa que f
y x
son los argumentos a la cifra resultante, que de este modo significa que el cuerpo de esa lambda será f
aplicado a x
una vez menos que n
.
A continuación, se aplica n
a tres argumentos. Esta es la parte difícil.
El segundo argumento, que corresponde a Z
de antes, es λu.x
--una función constante que ignora un argumento y devuelve x
.
El primer argumento, que corresponde a S
de antes, es λgh.h (g f)
. Podemos reescribir esto como λg. (λh.h (g f))
para reflejar el hecho de que solo se está aplicando el lambda externo n
veces. Lo que hace esta función es tomar el resultado acumulado hasta g
y devolver una nueva función tomando un argumento, que aplica ese argumento al g
aplicado a f
. Lo cual es absolutamente desconcertante, por supuesto.
Entonces ... ¿qué está pasando aquí? Considere la sustitución directa con S
y Z
. En un número distinto de cero Sn
, el n
corresponde al argumento vinculado a g
. Así, recordando que f
y x
están unidos en un ámbito exterior, podemos contar de esta manera: λu.x
, λh. h ((λu.x) f)
, λh'. h' ((λh. h ((λu.x) f)) f)
... Realización de las reducciones evidentes, obtenemos lo siguiente: λu.x
, λh. h x
, λh'. h' (f x)
...El patrón aquí es que una función se pasa "hacia adentro" una capa, en cuyo punto se aplicará un S
, mientras que Z
la ignorará. Entonces obtenemos una aplicación de f
para cada S
excepto la más externa.
El tercer argumento es simplemente la función identidad, que se aplica debidamente por la más externa S
, devolviendo el result-- final de f
aplica uno menos veces que el número de capas S
n
corresponde a.
La notación lambda es difícil de seguir, así que he hecho reducciones paso a paso con las expresiones S utilizando Clojure para '(pred zero)', '(pred one)' y '(pred two)' y [lo publicó en Github.] (https://github.com/abiro/church-encoding/blob/master/src/church_encoding/pred_reductions.clj) –