A maioria dos tutoriais sobre o Cálculo Lambda fornece um exemplo em que números inteiros positivos e booleanos podem ser representados por funções. E quanto a -1 e eu?
A maioria dos tutoriais sobre o Cálculo Lambda fornece um exemplo em que números inteiros positivos e booleanos podem ser representados por funções. E quanto a -1 e eu?
Primeiro codifique números e pares naturais, conforme descrito por jmad.
Represente um número inteiro como um par de números naturais tal que . Em seguida, você pode definir as operações usuais em números inteiros como (usando a notação Haskell para -calculus):( a , b ) k = a - b λ
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)
O caso de números complexos é semelhante no sentido em que um número complexo é codificado como um par de reais. Mas uma pergunta mais complicada é como codificar reais. Aqui você tem que fazer mais trabalho:
Codificar reais é muito trabalhoso e você não deseja realmente fazê-lo no -calculus. Mas veja, por exemplo, o subdiretório Marshall, para uma simples implementação de reais em puro Haskell. Isso poderia, em princípio, ser traduzido para o λ- cálcio puro .etc/haskell
i:ℤ
,x:a
,f,u,s:a→a
,p:(a→a,a→a)
] Se codificar ℤ como(Sign,ℕ)
em seguida, dado um par de funções(s,f)
comop
, o termoλi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
irão produzir tantof(…f(x)…)
ous(f(…f(x)…))
(se o resultado for negativo). Se você codificar ℤ como(ℕ,ℕ)
, precisará de uma função que tenha um inverso - dado um par(f,u)
ex
, a funçãoλi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
produzirá au(…u(f(…f(x)…))…)
qual deixará os temposf
aplicados . Ambos funcionam em contextos diferentes (o resultado pode ser "invertido" || é invertível).i
x
f
fold . ctor
para qualquer construtor e esse tipofold
(r
). (É por isso que, para os tipos de recursiva, os dados serão "recurse por conta própria" Para os tipos não-recursiva é mais como um.case
/ Correspondência de padrão.)O cálculo lambda pode codificar a maioria das estruturas de dados e tipos básicos. Por exemplo, você pode codificar um par de termos existentes no cálculo lambda, usando a mesma codificação da Igreja que você normalmente vê para codificar números inteiros não negativos e booleanos:
fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )
Em seguida, o par é p = ( emparelhar um b ) e se você quiser voltar a e b que você pode fazer ( FST p ) e ( SND p ) .( a , b ) p = ( par a b ) uma b ( primeiro p ) ( snd p )
Isso significa que você pode facilmente representar números inteiros positivos e negativos com um par: o sinal à esquerda e o valor absoluto à direita. O sinal é um booleano que especifica se o número é positivo. O direito é um número natural usando a codificação da Igreja.
E agora que você tem números inteiros relativos. A multiplicação é fácil de definir, basta aplicar a funçãoxor no sinal e a multiplicação em números naturais no valor absoluto:
Para definir a adição, você deve comparar dois números naturais e usar subtração quando os sinais forem diferentes; portanto, esse não é um termo λ, mas você pode adaptá-lo se realmente quiser:
mas a subtração é realmente fácil de definir:
fonte