Premessa
Ciao! Se è la prima volta che capiti su questo sito, ti consiglio di consultare la pagina principale di questo cosiddetto Giardino Digitale per scoprire meglio cos’è e come navigarlo.
Lo stato di questa nota è al momento: 🟡 Incompleta.
Con l’introduzione a variabili, astrazioni, applicazioni, operazioni come la -riduzione e metodi come il currying, abbiamo tutto quel che ci serve per trasformare il -calcolo in un linguaggio di programmazione Turing-completo (tramite l’implementazione di strumenti fondamentali nella programmazione come cicli, tipi di dati basilari e strutture dati più complicate), esattamente come dimostrato nella tesi di Church-Turing.
Per fare ciò, Church ha ideato una sua codifica, la codifica di Church, che permette di esprimere coerentemente (dal punto di vista semantico) tutti i costrutti fondamentali della computazione esclusivamente mediante il -calcolo.
Definizione: codifica di Church
1 - Logica booleana e strutture di controllo
Partendo dai classici valori booleani e , Church nella sua codifica decise di definirli seguendo una semplice regola: presi due valori in input e (tramite currying), TRUE restituirà il primo valore () e FALSE il secondo ():
Definizione: valori booleani nella codifica di Church
Nella codifica di Church, i valori booleani vero e falso sono rispettivamente codificati nei termini e definiti come segue:
Questa definizione di e può sembrare completamente arbitraria e senza senso così da sola, ma se codifichiamo un termine (che rappresenta una struttura di controllo) come
e applichiamo questo termine nel seguente modo:
allora possiamo dimostrare che verrà correttamente restituito il termine e, se calcoliamo invece il risultato di
otterremo il termine , esattamente come vorremmo che si comportasse una struttura di controllo.
Definizione: struttura di controllo nella codifica di Church
Nella codifica di Church, la struttura di controllo è codificata nel termine definito come segue:
Ora verifichiamo formalmente che l’ si comporta come vorremmo.
Verifica della correttezza semantica dell'
Sia l’insieme di termini del -calcolo.
Dati due termini :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
Ovviamente, quando andremo a “programmare” realmente tramite il -calcolo, al posto di e ci saranno delle espressioni booleane codificate in -calcolo che, appunto, si ridurranno nei valori e .
Osservazione: usare l' in un linguaggio zelante
Osserviamo cosa succede se proviamo a usare l’ in un linguaggio zelante, ossia usando l’ordine applicativo.
Proviamo per esempio a ridurre la -espressione usando l’ordine applicativo:
Arrivati a questo punto, non possiamo ridurre ulteriormente , ottenendo così un termine che, nel concreto, ci serve poco o niente. Ecco perché si preferisce sempre usare l’ordine normale nell’ambito della codifica di Church.
1.1 - Negazione logica
Avendo codificato i valori booleani e e un che si comporta come ci aspetteremmo, ora possiamo creare condizioni booleane più elaborate provando a codificare anche gli operatori booleani.
Per esempio, una semplice negazione logica potrebbe funzionare così: preso in input un argomento , se () è vero allora restituisce falso (FALSE), altrimenti restituisce vero (TRUE):
Definizione: negazione logica nella codifica di Church
Nella codifica di Church, la negazione logica è codificata nel termine definito come segue:
Verifichiamo che semanticamente il si comporti come ci aspettiamo.
Verifica della correttezza semantica del
1.2 - Congiunzione logica
Per la congiunzione logica , presi in input due argomenti e , se () è vero allora restituisce il valore di (perché da dipenderà se l’ è vero o falso), altrimenti (essendo già falso) restituisce il valore falso ():
Definizione: congiunzione logica nella codifica di Church
Nella codifica di Church, la congiunzione logica è codificata nel termine definito come segue:
Verifica della correttezza semantica dell'
- La -espressione è convertibile in :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
1.3 - Disgiunzione logica
Per la disgiunzione logica , presi in input due argomenti e , se () è vero allora restituisce vero (), altrimenti restituisce il valore di (perché da dipenderà se l’ è vero o falso):
Definizione: disgiunzione logica nella codifica di Church
Nella codifica di Church, la disgiunzione logica è codificata nel termine definito come segue:
Verifica della correttezza semantica dell'
- La -espressione è convertibile in :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
2 - Coppie di termini
Definizione: coppie nella codifica di Church
Nella codifica di Church, le coppie sono codificate nel termine definito come segue:
Il primo elemento della coppia è codificato nel termine definito come segue:
Il secondo elemento della coppia è codificato nel termine definito come segue:
Verifica della correttezza semantica di PAIR, FIRST e SECOND
Sia l’insieme di termini del -calcolo.
Dati due termini :
- La -espressione è convertibile in :
- La -espressione è convertibile in :
3 - Numerali di Church
Può sembrare scontato, ma uno strumento importante in ogni linguaggio di programmazione sono i numeri, uno dei tipi di dato più utili in un linguaggio.
Nella sua codifica, Alonzo Church ha deciso di rappresentare ogni numero naturale , detto numerale di Church e rappresentato come , come una funzione che mappa una qualsiasi funzione alla sua composizione per volte:
Prima di andare avanti, definiamo un attimo più formalmente questa notazione “esponenziale” dell’applicazione.
Definizione: applicazione esponenziale
Ritornando ai numerali, per un numero naturale qualsiasi, data una funzione e un parametro , verrà restituito il parametro su cui viene applicata la funzione per volte:
Possiamo quindi formalmente definire i numerali di Church.
Definizione: numerale di Church
Nella codifica di Church, un numerale di Church è un termine che codifica un numero naturale ed è definito come segue:
Ecco una breve tabella che riassume il comportamento dei numerali di Church:
| Numerale di Church | Definizione del numerale | Utilizzo del numerale |
|---|---|---|
Osservazione: numerali di Church come codifica unaria dei numeri naturali
I numerali di Church costituiscono una codifica unaria dei numeri naturali, ossia rappresentano un numero n come n applicazioni di una funzione.
La codifica unaria ha il vantaggio della semplicità concettuale e della chiarezza semantica, ma non è efficiente nei casi pratici per numeri grandi, proprio perché ogni numero è “codificato” con un numero di applicazioni proporzionale al valore numerico.
3.1 - Successore naturale
Nell’ambito dei numerali di Church, introduciamo un operatore, , che ci permette di ottenere il successore di un certo numerale (es. ).
Per far ciò, partiamo dalla definizione del numerale di Church (): prendendo in input un numerale (), gli applichiamo un’altra volta ancora :
Definizione: successore naturale nella codifica di Church
Nella codifica di Church, il successore naturale è codificato nel termine definito come segue:
Ora verifichiamo che , per come l’abbiamo definito, si comporti come vorremmo.
Verifica della correttezza semantica di
Dato un numerale di Church , vale:
Dimostrazione della correttezza semantica di
SUCC n=(a.f.x.a f (f x)) (f.x.fn x)\toβ(f.x.a f (f x))[(f.x.fn x)/a]=f.x.f.x.fn x) f (f x)\toβf.x.(x.fn x)[f/f] (f x)=f.x.(x.fn x) (f x)\toβf.x.(fn x)[(f x)/x]=f.x.fn (f x)=f.x.fn+1 x=SUCC n+1definizione di SUCC e del numerale di Church n-riduzionesostituzione-riduzionesostituzione-riduzionesostituzionedefinizione dell’applicazione esponenzialedefinizione del numerale di Church
3.2 - Predecessore naturale
Vogliamo ottenere una funzione PRED tale che:
PRED n=n-1
con PRED 0=0.
Prendendo ispirazione da SUCC, definito come
SUCC\overset{\text{def}}{=}a.f.x.a f (f x)
possiamo notare che, per calcolare il successoreLINK di un numero naturale, basta aggiungergli un’applicazione. Viceversa, per calcolare il suo predecessoreLINK, dovremo togliere un’applicazione.
Tuttavia, nel -calcolo, non è possibile togliere applicazioni a una funzione di Church. Occorre quindi un espediente funzionale.
L’idea di Church è questa: quando applichiamo una funzione f per n volte, vogliamo tener traccia non solo dell’ultimo risultato, ma anche del penultimo. Se riuscissimo a costruire una sequenza di coppie
(0,0),(0,1),(1,2),(2,3),…,(n-2,n-1),(n-1,n)
alla fine potremmo restituire il primo elemento della coppia finale per ottenere n-1.
Perciò, costruiamo una funzione “iteratrice” next(x) che parte da x=(0,0) e ad ogni passo aggiorna la coppia in questo modo:
next(x)=(x1second(x),x2succ(second(x)))
Così facendo, la funzione next(x) funzionerà nel seguente modo:
| x | x1=second(x) | x2=succ(second(x)) | next(x)=(x1,x2) |
|---|---|---|---|
| (0,0) | second((0,0))=0 | succ(second((0,0)))=succ(0)=1 | next((0,0))=(0,1) |
| (0,1) | second((0,1))=1 | succ(second((0,1)))=succ(1)=2 | next((0,1))=(1,2) |
| (1,2) | second((1,2))=2 | succ(second((1,2)))=succ(2)=3 | next((1,2))=(2,3) |
| (2,3) | second((2,3))=3 | succ(second((2,3)))=succ(3)=4 | next((2,3))=(3,4) |
| … | … | … | … |
| (n-2,n-1) | second((n-2,n-1))=n-1 | succ(second((n-2,n-1)))=succ(n-1)=n | next((n-2,n-1))=(n-1,n) |
| (n-1,n) | second((n-1,n))=n | succ(second((n-1,n)))=succ(n)=n+1 | next((n-1,n))=(n,n+1) |
Osserviamo che dopo n passi di next(x), la prima componente (x1) è esattamente n-1 (per n>0).
Nel -calcolo traduciamo questa funzione next(x) come:
NEXT\overset{\text{def}}{=}p.PAIR (SECOND p) (SUCC (SECOND p))
La nostra -espressione PRED dovrà quindi prendere la prima componente (FIRST) della coppia generata all’n-esima iterazione di NEXT:
PRED\overset{\text{def}}{=}n.FIRST (n NEXT (PAIR 0 0))
Definizione: predecessore naturale nella codifica di Church
Nella codifica di Church, il predecessore naturale è codificato nel termine PRED definito come segue:
PRED\overset{\text{def}}{=}n.FIRST (n NEXT (PAIR 0 0))
dove
NEXT\overset{\text{def}}{=}p.PAIR (SECOND p) (SUCC (SECOND p))
Verifica della correttezza semantica di PRED
Dato un numerale di Church n:
- Il successore della coppia (n-1,n) è (n,n+1):
NEXT (PAIR n-1 n)⇔PAIR n n+1
- Il predecessore di 0 è 0 e il predecessore di n è n-1:
PRED n⇔{0n-1n=0n>0
3.3 - Addizione
Definizione: addizione nella codifica di Church
Nella codifica di Church, l’addizione è codificata nel termine ADD definito come segue:
ADD\overset{\text{def}}{=}a.b.b SUCC a
Verifica della correttezza semantica di ADD
Dati due numerali di Church m e n, vale:
ADD m n⇔m+n
Dimostrazione della correttezza semantica di ADD
ADD m n=(a.b.b SUCC a) m n\toβ(b.b SUCC a)[m/a] n=(b.b SUCC m) n\toβ(b SUCC m)[n/b]=n SUCC m=(f.x.fn x) SUCC m\toβ(x.fn x)[SUCC/f] m=(x.SUCCn x) m\toβ(SUCCn x)[m/x]=SUCCn m=n volteSUCC (SUCC (… (SUCC m)))⇔n volte(((m+1)+1)…)+1=m+ndefinizione di ADD-riduzionesostituzione-riduzionesosituzionedefinizione dei numerali di Church-riduzionesostituzione-riduzionesostituzioneapplicazione esponenzialesemantica di SUCCaddizione
3.4 - Moltiplicazione
Definizione: moltiplicazione nella codifica di Church
Nella codifica di Church, la moltiplicazione è codificata nel termine MUL definito come segue:
MUL\overset{\text{def}}{=}a.b.b (ADD a) 0
3.5 - Esponenziazione
Definizione: esponenziazione nella codifica di Church
Nella codifica di Church, l’esponenziazione è codificata nel termine EXP definito come segue:
EXP\overset{\text{def}}{=}a.b.b (MUL a) 1
3.6 - Test per zero
Definizione: test per zero nella codifica di Church
Nella codifica di Church, il test per zero è codificato nel termine ISZERO definito come segue:
ISZERO\overset{\text{def}}{=}a.a (x.FALSE) TRUE
Verifica della correttezza semantica di ISZERO
Dato un numerale di Church n, se n=0 allora ISZERO n restituisce TRUE, altrimenti FALSE:
ISZERO n⇔{TRUEFALSEn=0n=0
4 - Punti fissi e funzioni ricorsive
Ora che abbiamo le operazioni aritmetiche per calcolare con i numerali di Church, possiamo cimentarci nella codifica di una prima funzione ricorsiva nel -calcolo: il fattoriale.
Il fattoriale di un numero naturale n, tradizionalmente, nella sua definizione ricorsiva si esprime come il n moltiplicato per il fattoriale del suo predecessore n-1 (con il fattoriale di 0 uguale a 1):
n!={1n∗(n-1)!n=0n>0
Come primo tentativo, potremmo tradurre questa definizione ricorsiva del fattoriale nella codifica di Church così:
FACT\overset{\text{def}}{=}a.IF (ISZERO a) 1 (MUL a (FACT (PRED a)))
Tuttavia, ciò non ci soddisfa perché il termine FACT compare pure a destra. Proviamo però ad astrarre ulteriormente questo termine passandogli il FACT nella sua definizione come argomento:
FACT\overset{\text{def}}{=}(f.a.IF (ISZERO a) 1 (MUL a (f (PRED a)))) FACT
(Ovviamente possiamo notare che, tramite un semplice passaggio di -riduzione, sostituiamo f con FACT e torniamo alla situazione iniziale.)
Assegniamo momentaneamente al termine “ausiliare” AUX tutto quell’ambaradan a cui va poi applicato ricorsivamente FACT:
AUX\overset{\text{def}}{=}f.a.IF (ISZERO a) 1 (MUL a (f (PRED a)))
In qualche modo, una definizione “accettabile” del fattoriale che vogliamo ottenere avrà una forma del tipo:
FACT\overset{\text{def}}{=}AUX AUX AUX …
Ma a noi serve avere una definizione finita per poter operare con questo termine e ottenere il risultato che vogliamo. È per questo che ci torna utile il concetto di punto fisso di una funzione che ci permetterà di definirla in maniera finita.
Non preoccuparti, a breve sarà tutto più chiaro, ma intanto beccati questa definizione di un punto fisso nel -calcolo espresso mediante questo particolare combinatore scoperto da Haskell Curry: il combinatore di punto fisso.
Definizione: combinatore di punto fisso Y
Il combinatore di punto fisso (anche detto combinatore di Curry perché scoperto da Haskell Curry) Y è un combinatore definito nel seguente modo:
Y\overset{\text{def}}{=}f.(x.f(x x)) (x.f(x x))
Possiamo dimostrare che questo combinatore di punto fisso Y si comporta semanticamente proprio come un punto fisso.
Verifica della correttezza semantica del combinatore di punto fisso Y
4.1 - Fattoriale
Il combinatore di punto fisso Y è uno strumento molto potente: ci permette, infatti, di implementare il concetto di ricorsione in un linguaggio, quello del -calcolo, che formalmente non ce l’ha.
Ciò infatti è possibile perché, ogni termine M a cui viene applicato il combinatore di punto fisso Y, diventa a sua volta l’argomento della -espressione di partenza:
Y M=M (Y M)=M (M (Y M))=M (M (M (Y M)))=…
Riprendendo quel termine “ausiliare” di prima, che abbiamo espresso come
AUX\overset{\text{def}}{=}f.a.IF (ISZERO a) 1 (MUL a (f (PRED a)))
possiamo renderci ora conto che, passandogli come argomento al posto della f il combinatore di punto fisso Y, ci aiuta a definire in maniera finita la funzione fattoriale nel -calcolo.
Definizione: fattoriale nella codifica di Church
Nella codifica di Church, il fattoriale è codificato nel termine FACT definito come segue:
FACT\overset{\text{def}}{=}(f.a.IF (ISZERO a) 1 (MUL a (f (PRED a)))) Y
Sì, ma siamo sicuri che quella che abbiamo appena scritto non sia una cazzata colossale e che effettivamente la ricorsione funzioni? Verifichiamolo.
Verifica della ricorsione nel fattoriale nella codifica di Church
Il termine FACT è convertibile nel seguente modo:
FACT⇔a.IF (ISZERO a) 1 (MUL a (FACT (PRED a)))
Fonti
- 🏫 Corso di Laurea in Informatica (
L-31 R) presso l’Università di Torino:
- Corso di Linguaggi e Paradigmi di Programmazione, A.A. 2020-21 (pagina Moodle):
- Prof. Luca Padovani, slide del corso:
- Corso di Linguaggi e Paradigmi di Programmazione, A.A. 2025-26 (pagina Moodle):
- Prof. Viviana Bono, lezioni del corso.
- 📹 Eyesomorphic, Programming with Math | The Lambda Calculus su YouTube.
- 🌐 Lambda-calcolo su Wikipedia in lingua italiana, archiviato sulla Wayback Machine in data 25 novembre 2025.
- 🌐 Simply typed lambda calculus su Wikipedia in lingua inglese, archiviato sulla Wayback Machine in data 25 novembre 2025.