Réponses:
D'abord encoder des nombres naturels et des paires, comme décrit par jmad.
Représente un entier comme une paire de nombres naturels ( a , b ) tels que k = a - b . Ensuite, vous pouvez définir les opérations habituelles sur les entiers comme (en utilisant la notation Haskell pour λ -calculus):
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)
Le cas des nombres complexes est similaire en ce sens qu'un nombre complexe est codé comme une paire de réels. Mais une question plus compliquée est de savoir comment coder les réels. Ici, vous devez faire plus de travail:
Encoder des réels demande beaucoup de travail et vous ne voulez pas vraiment le faire dans le -calculus. Mais voir par exemple le sous - répertoire de Marshall pour une implémentation simple des réels en Haskell pur. Cela pourrait en principe être traduit par le λ -calculus pur .etc/haskell
i:ℤ
, x:a
, f,u,s:a→a
, p:(a→a,a→a)
] Si vous encodez ℤ comme (Sign,ℕ)
alors, étant donné une paire de fonctions (s,f)
que p
le terme λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
produira soit f(…f(x)…)
ou s(f(…f(x)…))
(si le résultat est négatif). Si vous encodez ℤ as (ℕ,ℕ)
, vous avez besoin d'une fonction qui a une inverse - étant donné une paire (f,u)
et x
, la fonction λi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
produira u(…u(f(…f(x)…))…)
ce qui laissera f
les i
temps appliqués à x
. Les deux fonctionnent dans des contextes différents (le résultat peut être "inversé" || f
est inversible).
fold . ctor
pour tout constructeur et ce type fold
( r
). (C'est pourquoi, pour les types récursifs, les données seront "récursives par elles-mêmes". Pour les types non récursifs, cela ressemble plus à une case
correspondance de modèle /.)
Le lambda-calcul peut coder la plupart des structures de données et des types de base. Par exemple, vous pouvez encoder une paire de termes existants dans le calcul lambda, en utilisant le même encodage Church que vous voyez habituellement pour encoder des entiers non négatifs et booléens:
fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )
Alors la paire est p = ( paire a b ) et si vous voulez récupérer a et b vous pouvez faire ( fst p ) et ( snd p ) .
Cela signifie que vous pouvez facilement représenter des entiers positifs et négatifs avec une paire: le signe à gauche et la valeur absolue à droite. Le signe est un booléen qui spécifie si le nombre est positif. La droite est un nombre naturel utilisant le codage Eglise.
Pour définir l'addition, vous devez comparer deux nombres naturels et utiliser la soustraction lorsque les signes sont différents, donc ce n'est pas un terme λ mais vous pouvez l'adapter si vous voulez vraiment:
but then subtraction is really easy to define:
Once you have positive and negative integers you can define complex integers very easily: it is just a pair of two integers which represents . Then addition is point-wise and multiplication is as usual, but I won't write it, it should be easy: