Rappresentazione di numeri negativi e complessi mediante il calcolo Lambda


Risposte:


18

Prima codifica i numeri e le coppie naturali, come descritto da jmad.

Rappresenta un numero intero K come coppia di numeri naturali (un',B) tale che . Quindi puoi definire le normali operazioni sugli interi come (usando la notazione di Haskell per -calculus):λK=un'-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)

Il caso dei numeri complessi è simile nel senso che un numero complesso è codificato come una coppia di reali. Ma una domanda più complicata è come codificare i reali. Qui devi fare più lavoro:

  1. Codifica un numero razionale q come coppia (K,un') dove K è un numero intero, un' è naturale e q=K/(1+un') .
  2. Codifica un numero reale con una funzione f tale che per ogni naturale k N , f k codifica un numero razionale q tale che | x - q | < 2 - k . In altre parole, un reale è codificato come una sequenza di razionali che convergono ad esso alla velocità k 2 - k .XfKNfKq|X-q|<2-Kk2k

La codifica di reals richiede molto lavoro e non si desidera farlo effettivamente nel calcolo . Ma vedi ad esempio la sottodirectory di Marshall per una semplice implementazione dei reali in puro Haskell. In linea di principio, ciò potrebbe essere tradotto nel puro calcolo λ .λetc/haskellλ


1
Wow =) Mi chiedo intuitivamente cosa significhi ... per esempio, usando la codifica dei numeri di chiesa ... cioè. un numero di chiesa di valore intero n è rappresentato da una funzione che applica una funzione a un valore n volte. Le coppie e i valori lambda negativi hanno quella sensazione intuitiva simile su di loro?
zcaudate,

1
La codifica della chiesa codifica i numeri naturali , 1 , 2 , ... Non codifica i numeri negativi. Nella risposta sopra ho supposto che tu sapessi già di una codifica di numeri naturali, quindi ho spiegato come ottenere numeri interi. I numeri interi come li ho codificati sono una costruzione più formale, a differenza dei numeri della Chiesa, che sono collegati in modo più intricato con il calcolo λ . Non credo che i "valori lambda negativi" siano una frase significativa. 012λ
Andrej Bauer,

@zcaudate [annotazioni di tipo: i:ℤ, x:a, f,u,s:a→a, p:(a→a,a→a)] Se si codificano ℤ come (Sign,ℕ)allora, data una coppia di funzioni (s,f)come p, il termine λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)produrrà sia f(…f(x)…)o s(f(…f(x)…))(se il risultato è negativo). Se codifichi ℤ come (ℕ,ℕ), hai bisogno di una funzione che ha un'inverso - data una coppia (f,u)e x, la funzione λi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)produrrà a u(…u(f(…f(x)…))…)cui lasceranno i tempi fapplicati . Entrambi funzionano in contesti diversi (il risultato può essere "capovolto" || è invertibile). ixf
nessuno,

@zcaudate Le funzioni extra sono necessarie perché i numeri codificati dalla Chiesa "si basano da soli", ma le coppie ti consegneranno solo i loro componenti. Le funzioni di supporto incollano semplicemente i componenti insieme nell'ordine "giusto" (che sta accadendo automaticamente per nats.) Vedi anche: en.wikipedia.org/wiki/… - La codifica della chiesa è sostanzialmente fold . ctorper qualsiasi costruttore e quel tipo fold( r). (Ecco perché, per i tipi ricorsivi, i dati "ricorrono da soli". Per i tipi non ricorsivi è più simile a una casecorrispondenza / pattern.)
nessuno

13

Il lambda-calcolo può codificare la maggior parte delle strutture di dati e dei tipi di base. Ad esempio, puoi codificare una coppia di termini esistenti nel calcolo lambda, usando la stessa codifica Church che di solito vedi per codificare interi non negativi e booleano:

fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )

paio=λXyz.zXy
FST=λp.p(λXy.X)
snd=λp.p(λXy.y)

Poi la coppia è p = ( accoppiare  un b ) e se si vuole tornare a e b si può fare ( FST  p ) e ( snd  p ) .(un',B)p=(paio un'B)un'B(FST p)(snd p)

Ciò significa che puoi rappresentare facilmente numeri interi positivi e negativi con una coppia: il segno a sinistra e il valore assoluto a destra. Il segno è un valore booleano che specifica se il numero è positivo. Il diritto è un numero naturale che usa la codifica della Chiesa.

(sign,n)

E ora che hai numeri interi relativi. La moltiplicazione è facile da definire, devi solo applicare la funzione xor sul segno e la moltiplicazione su numeri naturali sul valore assoluto:

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

Per definire l'aggiunta, devi confrontare due numeri naturali e usare la sottrazione quando i segni sono diversi, quindi questo non è un termine λ ma puoi adattarlo se vuoi davvero:

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|

ma poi la sottrazione è davvero facile da definire:

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

(a,b)a+bi

add[i]=λz1z2.pair(add(fst z1)(fst z2))(add(snd z1)(snd z2))

6
Puoi evitare le distinzioni tra maiuscole e minuscole se invece rappresenti il ​​numero intero K come una coppia di numeri naturali (un',B) tale che K=un'-B.
Andrej Bauer,

Gli interi complessi vanno bene, ma stava chiedendo numeri complessi. D'altra parte, ovviamente, non possono mai essere rappresentati poiché non sono numerabili.
HdM,

@AndrejBauer: trucco molto bello (forse non così semplice) HdM: sicuro che possono farlo, anche in non tutti. Ma ho pensato che il metodo per costruire cose nel calcolo λ con la codifica della Chiesa fosse più importante / appropriato qui.
jmad

Vorrei poter dare due risposte corrette =) Non pensavo nemmeno che i reali potessero essere rappresentati quando ho chiesto numeri complessi, ma eccoti qui !.
zcaudate,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.