Représentation de nombres négatifs et complexes à l'aide du calcul lambda

14

La plupart des didacticiels sur Lambda Calculus fournissent un exemple où les entiers positifs et les booléens peuvent être représentés par des fonctions. Et -1 et moi?

zcaudate
la source

Réponses:

18

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):k(a,b)k=abλ

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:

  1. Encode un nombre rationnel comme une paire ( k , a )k est un entier, a est naturel et q = k / ( 1 + a )q(k,a)kaq=k/(1+a) .
  2. Coder un nombre réel par une fonction f telle que pour tout k naturel N , f k code un nombre rationnel q tel que | x - q | < 2 - k . En d'autres termes, un réel est codé comme une séquence de rationnels convergeant vers lui à la vitesse k 2 - k .xfkNfkq|xq|<2kk2k

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λ

Andrej Bauer
la source
1
Wow =) Je me demande intuitivement ce que cela signifie ... par exemple, en utilisant l'encodage des numéros d'église ... ie. un numéro d'église de valeur entière n est représenté par une fonction qui applique une fonction à une valeur n fois. Les paires et les valeurs lambda négatives ont-elles une impression intuitive similaire à leur sujet?
zcaudate
1
Le codage d'église code les nombres naturels , 1 , 2012 , ... Il n'encode pas les nombres négatifs. Dans la réponse ci-dessus, j'ai supposé que vous connaissiez déjà un codage de nombres naturels, j'ai donc expliqué comment obtenir des entiers. Les entiers tels que je les ai encodés sont une construction plus formelle, contrairement aux chiffres de l'Église, qui sont plus étroitement liés au -calculus. Je ne pense pas que "valeurs lambda négatives" soit une expression significative. λ
Andrej Bauer
@zcaudate [annotations de type: 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 ple 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 fles itemps appliqués à x. Les deux fonctionnent dans des contextes différents (le résultat peut être "inversé" || fest inversible).
personne le
@zcaudate Les fonctions supplémentaires sont nécessaires car les nombres encodés par l'Église "récursent d'eux-mêmes", mais les paires ne vous remettront que leurs composants. Les fonctions d'assistance collent simplement les composants ensemble dans le "bon" ordre (ce qui se produit automatiquement pour les nats.) Voir aussi: en.wikipedia.org/wiki/… - Le codage d'église est fondamentalement fold . ctorpour 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 casecorrespondance de modèle /.)
personne le
13

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 )

pair=λxyz.zxy
fst=λp.p(λxy.x)
snd=λp.p(λxy.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 ) .(a,b)p=(pair ab)ab(fst p)(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.

(sign,n)

xor

mult=λab.pair  (xor(fst a)(fst b))  (mult(snd a)(snd b))

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:

add=λab.{(true,add(snd a)(snd b))if a0b0(false,add(snd a)(snd b))if a<0b<0(true,sub(snd a)(snd b))if a0b<0|a||b|(false,sub(snd b)(snd a))if a0b<0|a|<|b|(true,sub(snd b)(snd a))if a<0b0|a|<|b|(false,sub(snd a)(snd b))if a<0b0|a||b|

but then subtraction is really easy to define:

minus=λa.pair(not(fst a))(snd a)
sub=λab.add(a)(minusb)

Once you have positive and negative integers you can define complex integers very easily: it is just a pair of two integers (a,b) which represents a+bi. Then addition is point-wise and multiplication is as usual, but I won't write it, it should be easy:

add[i]=λz1z2.pair(add(fst z1)(fst z2))(add(snd z1)(snd z2))
jmad
la source
6
You can avoid the case distinctions if instead you represent the integer k as a pair of natural numbers (a,b) such that k=ab.
Andrej Bauer
Complex integers alright, but he was asking for complex numbers. Then again, they of course can never be represented since there are uncountable.
HdM
@AndrejBauer: very nice trick (maybe not that simpler) HdM: sure they can, even in not all of them. But I figured that the method for building stuff in the λ-calculus with Church encoding was more important/appropriate here.
jmad
I wish I could give two correct answers =) I wasn't even thinking that reals could be represented when I asked about complex numbers but there you go!.
zcaudate