Ricorsione anonima
Un combinatore a punto fisso è una funzione di ordine superiore fix
che per definizione soddisfa l'equivalenza
forall f. fix f = f (fix f)
fix f
rappresenta una soluzione x
all'equazione del punto fisso
x = f x
Il fattoriale di un numero naturale può essere dimostrato da
fact 0 = 1
fact n = n * fact (n - 1)
L'uso di fix
prove costruttive arbitrarie sulle funzioni generali / μ ricorsive può essere derivato senza autoreferenzialità non mistica.
fact n = (fix fact') n
dove
fact' rec n = if n == 0
then 1
else n * rec (n - 1)
tale che
fact 3
= (fix fact') 3
= fact' (fix fact') 3
= if 3 == 0 then 1 else 3 * (fix fact') (3 - 1)
= 3 * (fix fact') 2
= 3 * fact' (fix fact') 2
= 3 * if 2 == 0 then 1 else 2 * (fix fact') (2 - 1)
= 3 * 2 * (fix fact') 1
= 3 * 2 * fact' (fix fact') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (fix fact') (1 - 1)
= 3 * 2 * 1 * (fix fact') 0
= 3 * 2 * 1 * fact' (fix fact') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (fix fact') (0 - 1)
= 3 * 2 * 1 * 1
= 6
Questa prova formale che
fact 3 = 6
utilizza metodicamente l'equivalenza del combinatore in virgola fissa per le riscritture
fix fact' -> fact' (fix fact')
Calcolo lambda
Il formalismo del calcolo lambda non tipizzato consiste in una grammatica senza contesto
E ::= v Variable
| λ v. E Abstraction
| E E Application
dove v
va oltre le variabili, insieme alle regole di riduzione beta ed eta
(λ x. B) E -> B[x := E] Beta
λ x. E x -> E if x doesn’t occur free in E Eta
La riduzione beta sostituisce tutte le occorrenze libere della variabile x
nel corpo dell'astrazione ("funzione") B
con l'espressione ("argomento") E
. La riduzione dell'ETA elimina l'astrazione ridondante. A volte viene omesso dal formalismo. Un'espressione irriducibile , alla quale non si applica alcuna regola di riduzione, è in forma normale o canonica .
λ x y. E
è una scorciatoia per
λ x. λ y. E
(astrazione multiarità),
E F G
è una scorciatoia per
(E F) G
(associazione sinistra associatività),
λ x. x
e
λ y. y
sono equivalenti alfa .
Astrazione e applicazione sono gli unici due "primitivi linguistici" del calcolo lambda, ma consentono la codifica di dati e operazioni arbitrariamente complessi.
I numeri della Chiesa sono una codifica dei numeri naturali simili ai naturali Peano-assiomatici.
0 = λ f x. x No application
1 = λ f x. f x One application
2 = λ f x. f (f x) Twofold
3 = λ f x. f (f (f x)) Threefold
. . .
SUCC = λ n f x. f (n f x) Successor
ADD = λ n m f x. n f (m f x) Addition
MULT = λ n m f x. n (m f) x Multiplication
. . .
Una prova formale che
1 + 2 = 3
usando la regola di riscrittura della riduzione beta:
ADD 1 2
= (λ n m f x. n f (m f x)) (λ g y. g y) (λ h z. h (h z))
= (λ m f x. (λ g y. g y) f (m f x)) (λ h z. h (h z))
= (λ m f x. (λ y. f y) (m f x)) (λ h z. h (h z))
= (λ m f x. f (m f x)) (λ h z. h (h z))
= λ f x. f ((λ h z. h (h z)) f x)
= λ f x. f ((λ z. f (f z)) x)
= λ f x. f (f (f x)) Normal form
= 3
combinatori
Nel calcolo lambda, i combinatori sono astrazioni che non contengono variabili libere. Più semplicemente: I
il combinatore di identità
λ x. x
isomorfo alla funzione identità
id x = x
Tali combinatori sono gli operatori primitivi dei calcoli combinatori come il sistema SKI.
S = λ x y z. x z (y z)
K = λ x y. x
I = λ x. x
La riduzione della beta non si sta fortemente normalizzando ; non tutte le espressioni riducibili, "redexes", convergono in forma normale sotto la riduzione beta. Un semplice esempio è l'applicazione divergente del ω
combinatore omega
λ x. x x
a se stesso:
(λ x. x x) (λ y. y y)
= (λ y. y y) (λ y. y y)
. . .
= _|_ Bottom
Viene data la priorità alla riduzione delle sottoespressioni più a sinistra ("teste"). L'ordine applicabile normalizza gli argomenti prima della sostituzione, l'ordine normale no. Le due strategie sono analoghe alla valutazione avida, ad esempio C, e alla valutazione pigra, ad esempio Haskell.
K (I a) (ω ω)
= (λ k l. k) ((λ i. i) a) ((λ x. x x) (λ y. y y))
diverge sotto l'aspra riduzione beta dell'ordine applicativo
= (λ k l. k) a ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ y. y y) (λ y. y y))
. . .
= _|_
da quando in semantica rigorosa
forall f. f _|_ = _|_
ma converge sotto una pigra riduzione della beta di ordine normale
= (λ l. ((λ i. i) a)) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= a
Se un'espressione ha una forma normale, la riduzione beta dell'ordine normale la troverà.
Y
La proprietà essenziale del Y
combinatore a punto fisso
λ f. (λ x. f (x x)) (λ x. f (x x))
è dato da
Y g
= (λ f. (λ x. f (x x)) (λ x. f (x x))) g
= (λ x. g (x x)) (λ x. g (x x)) = Y g
= g ((λ x. g (x x)) (λ x. g (x x))) = g (Y g)
= g (g ((λ x. g (x x)) (λ x. g (x x)))) = g (g (Y g))
. . . . . .
L'equivalenza
Y g = g (Y g)
è isomorfo a
fix f = f (fix f)
Il calcolo lambda non tipizzato può codificare prove costruttive arbitrarie su funzioni generali / μ ricorsive.
FACT = λ n. Y FACT' n
FACT' = λ rec n. if n == 0 then 1 else n * rec (n - 1)
FACT 3
= (λ n. Y FACT' n) 3
= Y FACT' 3
= FACT' (Y FACT') 3
= if 3 == 0 then 1 else 3 * (Y FACT') (3 - 1)
= 3 * (Y FACT') (3 - 1)
= 3 * FACT' (Y FACT') 2
= 3 * if 2 == 0 then 1 else 2 * (Y FACT') (2 - 1)
= 3 * 2 * (Y FACT') 1
= 3 * 2 * FACT' (Y FACT') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (Y FACT') (1 - 1)
= 3 * 2 * 1 * (Y FACT') 0
= 3 * 2 * 1 * FACT' (Y FACT') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (Y FACT') (0 - 1)
= 3 * 2 * 1 * 1
= 6
(Moltiplicazione ritardata, confluenza)
Per il calcolo lambda non tipizzato della Chiesa, inoltre, è stato dimostrato che esiste un infinito ricorsivamente enumerabile di combinatori a punto fisso Y
.
X = λ f. (λ x. x x) (λ x. f (x x))
Y' = (λ x y. x y x) (λ y x. y (x y x))
Z = λ f. (λ x. f (λ v. x x v)) (λ x. f (λ v. x x v))
Θ = (λ x y. y (x x y)) (λ x y. y (x x y))
. . .
La riduzione beta dell'ordine normale rende il calcolo lambda non tipizzato non esteso un sistema di riscrittura completo di Turing.
In Haskell, il combinatore a punto fisso può essere implementato con eleganza
fix :: forall t. (t -> t) -> t
fix f = f (fix f)
La pigrizia di Haskell si normalizza fino alla fine prima che tutte le sottoespressioni siano state valutate.
primes :: Integral t => [t]
primes = sieve [2 ..]
where
sieve = fix (\ rec (p : ns) ->
p : rec [n | n <- ns
, n `rem` p /= 0])