É uma pena que grande parte da literatura sobre o assunto seja muito densa. Eu também estava no seu lugar. Tive minha primeira introdução ao assunto em Linguagens de Programação: Aplicações e Interpretação
http://www.plai.org/
Tentarei resumir a ideia abstrata seguida de detalhes que não achei imediatamente óbvios. Em primeiro lugar, a inferência de tipo pode ser pensada para gerar e, em seguida, resolver restrições. Para gerar restrições, você percorre novamente a árvore de sintaxe e gera uma ou mais restrições em cada nó. Por exemplo, se o nó for um+
operador, os operandos e os resultados devem ser todos números. Um nó que aplica uma função tem o mesmo tipo que o resultado da função e assim por diante.
Para uma linguagem sem let
, você pode resolver cegamente as restrições acima por substituição. Por exemplo:
(if (= 1 2)
1
2)
aqui, podemos dizer que a condição da instrução if deve ser booleana e que o tipo da instrução if é o mesmo que o tipo de suas cláusulas then
e else
. Visto que sabemos 1
e 2
somos números, por substituição, sabemos que a if
afirmação é um número.
Onde as coisas ficam feias, e o que eu não conseguia entender por um tempo, é lidar com isso:
(let ((id (lambda (x) x)))
(id id))
Aqui, associamos id
a uma função que retorna tudo o que você passou, também conhecido como função de identidade. O problema é que o tipo de parâmetro da função x
é diferente em cada uso de id
. A segunda id
é uma função do tipo a -> a
, onde a
pode ser qualquer coisa. O primeiro é do tipo (a -> a) -> (a -> a)
. Isso é conhecido como polimorfismo let. A chave é resolver as restrições em uma ordem particular: primeiro resolva as restrições para a definição de id
. Isso vai ser a -> a
. Em seguida, cópias novas e separadas do tipo de id
podem ser substituídas nas restrições de cada local id
, por exemplo a2 -> a2
e a3 -> a3
.
Isso não foi explicado prontamente nos recursos online. Eles mencionarão o algoritmo W ou M, mas não como eles funcionam em termos de resolução de restrições, ou por que ele não vomita no polimorfismo let: cada um desses algoritmos impõe uma ordem na resolução das restrições.
Achei este recurso extremamente útil para amarrar o Algoritmo W, M e o conceito geral de geração de restrição e resolução de todos juntos. É um pouco denso, mas melhor do que muitos:
http://www.cs.uu.nl/research/techreps/repo/CS-2002/2002-031.pdf
Muitos dos outros papéis também são bons:
http://people.cs.uu.nl/bastiaan/papers.html
Espero que ajude a esclarecer um mundo um tanto obscuro.