La mayoría de los tutoriales sobre el cálculo de Lambda proporcionan un ejemplo en el que los enteros positivos y los booleanos pueden representarse mediante funciones. ¿Qué pasa con -1 y yo?
14
La mayoría de los tutoriales sobre el cálculo de Lambda proporcionan un ejemplo en el que los enteros positivos y los booleanos pueden representarse mediante funciones. ¿Qué pasa con -1 y yo?
Primero codifique números y pares naturales, como lo describe jmad.
Representa un número entero como un par de números naturales tal que . Luego puede definir las operaciones habituales en enteros como (usando la notación de Haskell para cálculo ):
neg = \k -> (snd k, fst k)
add = \k m -> (fst k + fst m, snd k + snd m)
sub = \k m -> add k (neg m)
mul = \k m -> (fst k * fst m + snd k * snd m, fst k * snd m + snd k * fst m)
El caso de los números complejos es similar en el sentido de que un número complejo está codificado como un par de reales. Pero una pregunta más complicada es cómo codificar los reales. Aquí tienes que hacer más trabajo:
Codificar reales es mucho trabajo y no quieres hacerlo en el cálculo . Pero vea, por ejemplo, el subdirectorio de Marshall para una implementación simple de reales en Haskell puro. En principio, esto podría traducirse al cálculo λ puro .etc/haskell
i:ℤ
,x:a
,f,u,s:a→a
,p:(a→a,a→a)
] Si codifican ℤ como(Sign,ℕ)
entonces, dado un par de funciones(s,f)
comop
, el términoλi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
producirá ya seaf(…f(x)…)
os(f(…f(x)…))
(si el resultado es negativo). Si codifica ℤ como(ℕ,ℕ)
, necesita una función que tenga un inverso, dado un par(f,u)
yx
, la funciónλi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
produciráu(…u(f(…f(x)…))…)
lo que dejará los tiemposf
aplicados . Ambos funcionan en diferentes contextos (el resultado puede "voltearse" || es invertible).i
x
f
fold . ctor
para cualquier constructor y ese tipofold
(r
). (Es por eso que, para los tipos recursivos, los datos "recurrirán por sí mismos". Para los tipos no recursivos es más como unacase
coincidencia de patrón /.)El cálculo Lambda puede codificar la mayoría de las estructuras de datos y tipos básicos. Por ejemplo, puede codificar un par de términos existentes en el cálculo lambda, utilizando la misma codificación de Church que suele ver para codificar enteros no negativos y booleanos:
fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )
Entonces el par es p = ( emparejar un b ) y si quieres volver una y b se puede hacer ( FST p ) y ( SND p ) .(a,b) p=(pair ab) a b (fst p) (snd p)
Eso significa que puede representar fácilmente enteros positivos y negativos con un par: el signo a la izquierda y el valor absoluto a la derecha. El signo es un booleano que especifica si el número es positivo. El derecho es un número natural que usa la codificación de Church.
Y ahora que tienes enteros relativos. La multiplicación es fácil de definir, solo tiene que aplicar la funciónxor en el signo y la multiplicación en números naturales en el valor absoluto:
Para definir la suma, debe comparar dos números naturales y usar la resta cuando los signos son diferentes, por lo que este no es un término λ pero puede adaptarlo si realmente desea:
pero luego la resta es realmente fácil de definir:
fuente