[EDIT: Voilà qualche parola su ciascuno]
Esistono diversi modi per estendere l'inferenza del tipo HM. La mia risposta si basa su molti, più o meno riusciti, tentativi di attuazione di alcuni di essi. Il primo su cui mi sono imbattuto è il polimorfismo parametrico . I sistemi di tipo che cercano di estendere l'HM in questa direzione tendono verso il Sistema F e quindi richiedono annotazioni di tipo. Due estensioni notevoli in questa direzione in cui mi sono imbattuto sono:
HMF, consente l'inferenza di tipo per tutti i tipi di System-F, il che significa che è possibile avere una quantificazione universale "nel mezzo" di un tipo, il loro aspetto non è implicitamente situato nell'ambito più elevato come per i tipi polimorfici di HM. Il documento afferma chiaramente che non esiste una regola chiara su quante e dove potrebbero essere necessarie le annotazioni dei tipi. Anche i tipi sono quelli del Sistema F, i termini di solito non hanno un tipo principale.
MLF non è solo un'estensione di HM, ma è anche un'estensione del Sistema F che riacquista la proprietà del tipo principale di HM introducendo una sorta di quantificazione limitata sui tipi. Un confronto è stato fatto dagli autori, MLF è strettamente più potente di HMF e le annotazioni sono necessarie solo per i parametri utilizzati polimorficamente.
Un altro modo di estendere HM è attraverso la variazione del dominio del vincolo.
HM (X) è Hindley-Milner parametrizzato su un dominio di vincolo X. In questo approccio, l'algoritmo HM genera i vincoli inviati a un risolutore di domini per X. Per il solito HM, il risolutore di domini è la procedura di unificazione e il dominio è costituito dell'insieme di termini compilato dai tipi e dalle variabili di tipo.
Un altro esempio di X potrebbe essere i vincoli espressi nella lingua dell'aritmetica di Presburger (nel qual caso l'inferenza / controllo del tipo è decidibile) o nella lingua dell'aritmetica di Peano (non più decidibile). X varia secondo uno spettro di teorie, ognuna con i propri requisiti per quanto riguarda la quantità e la localizzazione delle annotazioni dei tipi necessarie e che vanno dal non affatto a tutte.
Le classi di tipi di Haskell sono anche una sorta di estensione del dominio del vincolo aggiungendo predicati di tipo del modulo MyClass(MyType)
(nel senso che esiste un'istanza di MyClass per il tipo MyType).
Le classi di tipi conservano l'inferenza di tipo perché sono fondamentalmente concetti (quasi) ortogonali che implementano il polimorfismo ad hoc .
Ad esempio, prendi un simbolo val
di tipo val :: MyClass a => a
per il quale puoi avere istanze MyClass A
, MyClass B
ecc. Quando fai riferimento a quel simbolo nel tuo codice, è in realtà perché l'inferenza del tipo è già eseguita che il compilatore può inferire quale istanza della classe usare. Ciò significa che il tipo di val
dipende dal contesto in cui viene utilizzato. Questo è anche il motivo per cui l'esecuzione di una singola val
istruzione porta a unambiguous type error
: il compilatore non può inferire alcun tipo in base al contesto.
Per sistemi di tipo più avanzati come GADT, famiglie di tipi, tipi dipendenti, Sistema (F) ω, ecc., I tipi non sono più "tipi", ma diventano oggetti computazionali complessi. Ad esempio, significa che due tipi che non sembrano uguali non sono necessariamente diversi. Quindi l'uguaglianza dei tipi non diventa affatto banale (per niente).
Per darvi un esempio della complessità effettiva, consideriamo il tipo di elenco dipendente: NList a n
dove si a
trova il tipo di oggetti nell'elenco e la n
sua lunghezza.
La funzione append avrebbe tipo append :: NList a n -> NList a m -> NList a (n + m)
e la funzione zip sarebbe zip :: NList a n -> NList b n -> NList (a, b) n
.
Immagina ora di avere la lambda \a: NList t n, b: NList t m -> zip (append a b) (append b a)
. Qui il primo argomento di zip è di tipo NList t (n + m)
e il secondo di tipo NList t (m + n)
.
Quasi lo stesso, ma a meno che il verificatore del tipo non sappia che "+" commuta su numeri naturali, deve rifiutare la funzione perché (n + m) non è letteralmente (m + n). Non si tratta più di inferenza / verifica del tipo, ma di dimostrazione del teorema.
I tipi liquidi sembrano fare un'inferenza di tipo dipendente. Ma a quanto ho capito, non è un tipo realmente dipendente, più qualcosa come i soliti tipi HM su cui viene fatta un'inferenza aggiuntiva per calcolare i limiti statici.
Spero che aiuti.