Le funzioni di questo tipo sono spesso incontrate nella combinatori a virgola fissa. per esempio. una forma di Y combinator è scritta λf.(λx.f (x x)) (λx.f (x x))
. I combinatori a virgola fissa vengono utilizzati per implementare la ricorsione generale nel calcolo lambda non tipizzato senza alcun costrutto ricorsivo aggiuntivo, e questo fa parte di ciò che rende il calcolo lambda non tipizzato Turing-completo.
Quando le persone hanno sviluppato simply-typed lambda calculus, che è un sistema di tipo statico ingenuo in cima al calcolo lambda, hanno scoperto che non era più possibile scrivere tali funzioni. Infatti, non è possibile eseguire la ricorsione generale in lambda calcolo semplice; e quindi, il calcolo lambda semplicemente tipizzato non è più completo di Turing. (Un effetto collaterale interessante è che i programmi in modo semplice, digitato lambda calcolo sempre terminare.)
reale staticamente tipizzato linguaggi di programmazione come necessità standard ML built-in meccanismi ricorsivi per superare il problema, come ad esempio funzioni ricorsive nome (definito con val rec
o fun
) e con tipi di dati ricorsivi denominati.
È ancora possibile utilizzare tipi di dati ricorsivi per simulare qualcosa di simile a ciò che si desidera, ma non è così bello.
Fondamentalmente, si desidera definire un tipo come 'a foo = 'a foo -> 'a
; tuttavia, questo non è permesso. È invece avvolgerla in un tipo di dati: datatype 'a foo = Wrap of ('a foo -> 'a);
datatype 'a foo = Wrap of ('a foo -> 'a);
fun unwrap (Wrap x) = x;
Fondamentalmente, Wrap
e unwrap
sono utilizzati per trasformare tra 'a foo
e 'a foo -> 'a
, e viceversa.
Ogni volta che è necessario chiamare una funzione su sé stesso, invece di x x
, è necessario scrivere esplicitamente (unwrap x) x
(o unwrap x x
); Ad esempio, unwrap
lo trasforma in una funzione che è possibile applicare al valore originale.
P.S. Un altro linguaggio ML, OCaml, ha un'opzione per abilitare i tipi ricorsivi (normalmente disabilitati); se si esegue l'interprete o il compilatore con il flag -rectypes
, è possibile scrivere cose come fun x -> x x
. Fondamentalmente, dietro le quinte, il type-checker individua i punti in cui è necessario "avvolgere" e "scartare" il tipo ricorsivo, e quindi inserirli per te. Non sono a conoscenza di alcuna implementazione di standard ML con funzionalità di tipi ricorsivi simili.
Se qualcuno è interessato, ho scoperto che questo è chiamato [U Combinator (vedi in fondo alla pagina)] (http://www.ucombinator.org/), ma non è stato possibile trovare altro a riguardo. –
Non sapevo che fosse chiamato il combinatore U, ma come afferma quella pagina, è usato per compilare il programma (apparentemente più breve) non terminante del calcolo lambda non tipizzato che ho inserito nella mia risposta. –