È 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 thene else. Poiché conosciamo 1e 2siamo numeri, per sostituzione sappiamo che l' ifaffermazione è 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 ida 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 apuò 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 idpossono essere sostituite nei vincoli per ogni luogo idviene utilizzato, ad esempio a2 -> a2e 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.