Ci sono un paio di livelli alla tua prima domanda. Per inciso, tuttavia, ti consiglio di imparare a conoscere unification se non sei già familiare con esso in quanto è una parte fondamentale della comprensione del controllo di tipo e dell'inferenza di tipo.
Per digitare check selfApply fornisci provvisoriamente f il tipo a che risolviamo per. (A questo punto è solo una variabile di unificazione, la differenza chiave tra il controllo del tipo di Hindley-Milner e il controllo del tipo per i tipi semplici è che generalizzeremo (quantificeremo sopra) tutte le variabili non associate alla fine.) Poiché stiamo usando f come funzione sappiamo a = b -> c per le nuove variabili b e c . Poiché applichiamo f a qualcosa di tipo a , ovvero f stesso, sappiamo b = a . Non c'è alcun vincolo su c , quindi è corretto essere confusi sulla risposta fornita poiché f non è richiesto per essere a e a -> a e potrebbe effettivamente essere a e a -> a -> a o a e a -> Bool pure. Naturalmente, come sicuramente capisci, il problema è risolvere l'equazione a = a -> c . Nel tentativo di unificare questi con unificazione tradizionale, falliremo ciò che è noto come il controllo dei casi. Questo controllo è per evitare termini infiniti. L'unificazione razionale degli alberi è, tuttavia, un modo per affrontare questo problema e porta a tipi equi-ricorsivi. Haskell non supporta intenzionalmente i tipi equi-ricorsivi, ma O'Caml, ad esempio, fa con il flag -rectypes . Per convalidare che c è gratuito, possiamo usare un tipo iso -recursive, cioè:
data X c = X (X c -> c)
selfApply f = f (X f)
che scriverà check, e, in particolare, selfApply :: (X c -> c) -> c .
Ci sono due ragioni per cui Haskell (e quasi tutti i linguaggi polimorfici) non supportano i tipi equi-recursivi. Innanzitutto, in modo pragmatico, molti errori di tipo si presentano come tipi infiniti e se i tipi equi-recursivi erano supportati (tacitamente), si sarebbero trasformati in guasti ma avrebbero scritto programmi corretti. Più filosoficamente, la messa al bando dei tipi equi-recursivi e di cose simili era esattamente il motivo per cui i sistemi di tipo furono originariamente inventati risalendo fino a Bertrand Russell.