È un peccato che gran parte della letteratura sull'argomento sia molto densa. Anch'io ero nei tuoi panni. Ho avuto la mia prima introduzione all'argomento da Linguaggi di programmazione: applicazioni e interpretazione
http://www.plai.org/
Cercherò di riassumere l'idea astratta seguita da dettagli che non ho trovato subito evidenti. In primo luogo, si può pensare che l'inferenza di tipo generi e quindi risolva i vincoli. Per generare vincoli, si ricorre all'albero della sintassi e si generano uno o più vincoli su ogni nodo. Ad esempio, se il nodo è un +
operatore, gli operandi e i risultati devono essere tutti numeri. Un nodo che applica una funzione ha lo stesso tipo del risultato della funzione e così via.
Per una lingua senza let
, puoi risolvere ciecamente i vincoli di cui sopra per sostituzione. Per esempio:
(if (= 1 2)
1
2)
qui, possiamo dire che la condizione dell'istruzione if deve essere booleana e che il tipo dell'istruzione if è lo stesso del tipo delle sue clausole then
e else
. Poiché conosciamo 1
e 2
siamo numeri, per sostituzione sappiamo che l' if
affermazione è un numero.
Dove le cose si mettono male, e quello che non ho potuto capire per un po ', è avere a che fare:
(let ((id (lambda (x) x)))
(id id))
Qui, ci siamo associati id
a una funzione che restituisce tutto ciò che hai passato, altrimenti nota come funzione di identità. Il problema è che il tipo di parametro della funzione x
è diverso a ogni utilizzo di id
. Il secondo id
è una funzione del tipo a -> a
, dove a
può essere qualsiasi cosa. Il primo è di tipo (a -> a) -> (a -> a)
. Questo è noto come let-polimorfismo. La chiave è risolvere i vincoli in un ordine particolare: prima risolvere i vincoli per la definizione di id
. Questo sarà a -> a
. Quindi copie fresche e separate del tipo di id
possono essere sostituite nei vincoli per ogni luogo id
viene utilizzato, ad esempio a2 -> a2
e a3 -> a3
.
Ciò non è stato prontamente spiegato nelle risorse online. Menzioneranno l'algoritmo W o M ma non il modo in cui funzionano in termini di risoluzione dei vincoli, o il motivo per cui non si applica al polimorfismo letale: ciascuno di quegli algoritmi impone un ordine sulla risoluzione dei vincoli.
Ho trovato questa risorsa estremamente utile per collegare l'algoritmo W, M e il concetto generale di generazione e risoluzione dei vincoli tutti insieme. È un po 'denso, ma migliore di molti:
http://www.cs.uu.nl/research/techreps/repo/CS-2002/2002-031.pdf
Anche molti altri giornali sono carini:
http://people.cs.uu.nl/bastiaan/papers.html
Spero che questo aiuti a chiarire un mondo un po 'oscuro.