[EDIT: Voilà algumas palavras em cada]
Existem várias maneiras de estender a inferência do tipo HM. Minha resposta é baseada em muitas tentativas, mais ou menos bem-sucedidas, de implementar algumas delas. O primeiro que encontrei foi o polimorfismo paramétrico . Os sistemas de tipos que tentam estender o HM nessa direção tendem para o Sistema F e, portanto, requerem anotações de tipo. Duas extensões notáveis nessa direção que me deparei são:
HMF, permite a inferência de tipo para todos os tipos System-F, o que significa que você pode ter uma quantificação universal "no meio" de um tipo, sua aparência não está implicitamente situada no escopo mais alto, como nos tipos polimórficos HM. O documento afirma claramente que não existe uma regra clara sobre quantas e onde anotações de tipo podem ser necessárias. Além disso, sendo os tipos do Sistema F, os termos geralmente não têm um tipo principal.
O MLF não é apenas uma extensão do HM, é também uma extensão do Sistema F que recupera a propriedade de tipo principal do HM, introduzindo um tipo de quantificação limitada sobre os tipos. Uma comparação foi feita pelos autores, o MLF é estritamente mais poderoso que o HMF e as anotações são necessárias apenas para parâmetros usados polimorficamente.
Outra maneira de estender o HM é através da variação do domínio de restrição.
HM (X) é Hindley-Milner parametrizado em um domínio de restrição X. Nessa abordagem, o algoritmo HM gera as restrições enviadas a um solucionador de domínio para X. Para o HM usual, o solucionador de domínio é o procedimento de unificação e o domínio consiste em do conjunto de termos construídos a partir dos tipos e das variáveis de tipo.
Outro exemplo para X pode ser as restrições expressas no idioma da aritmética de Presburger (nesse caso, a inferência / verificação de tipo é decidível) ou no idioma da aritmética de Peano (não é mais decidível). X varia ao longo de um espectro de teorias, cada uma com seus próprios requisitos em relação à quantidade e localização das anotações de tipo necessárias e variando de nenhuma a todas elas.
As classes de tipo de Haskell também são um tipo de extensão do domínio de restrição, adicionando predicados de tipo do formulário MyClass(MyType)
(o que significa que existe uma instância de MyClass para o tipo MyType).
As classes de tipo preservam a inferência de tipo porque são basicamente conceitos (quase) ortogonais que implementam polimorfismo adhoc .
Como exemplo, tome um símbolo val
do tipo val :: MyClass a => a
para o qual você pode ter instâncias MyClass A
, MyClass B
etc. Quando você se referir a esse símbolo em seu código, é realmente porque a inferência de tipos já é realizado que o compilador pode inferir qual instância da classe para uso. Isso significa que o tipo de val
depende do contexto em que é usado. É também por isso que executar uma única val
instrução leva a umambiguous type error
: o compilador não pode inferir nenhum tipo com base no contexto.
Para sistemas de tipos mais avançados, como GADTs, famílias de tipos, tipos dependentes, System (F) ω, etc., o tipo não é mais "tipos", eles se tornam objetos computacionais complexos. Por exemplo, significa que dois tipos que não parecem iguais não são necessariamente diferentes. Portanto, a igualdade de tipos não se torna trivial.
Para dar um exemplo da complexidade real, vamos considerar o tipo dependente de lista: NList a n
onde a
está o tipo de objetos na lista e n
seu comprimento.
A função de acréscimo teria o tipo append :: NList a n -> NList a m -> NList a (n + m)
e a função zip seria zip :: NList a n -> NList b n -> NList (a, b) n
.
Imagine agora que temos a lambda \a: NList t n, b: NList t m -> zip (append a b) (append b a)
. Aqui, o primeiro argumento do zip é do tipo NList t (n + m)
e o segundo do tipo NList t (m + n)
.
Quase o mesmo, mas, a menos que o verificador de tipos saiba que "+" é comutado em números naturais, ele deve rejeitar a função porque (n + m) não é literalmente (m + n). Não se trata mais de inferência / verificação de tipo, mas de prova de teoremas.
Os tipos líquidos parecem estar fazendo alguma inferência de tipo dependente. Mas, pelo que entendi, não é realmente um tipo dependente, mais algo como os tipos comuns de HM, nos quais é feita uma inferência adicional para calcular limites estáticos.
Eu espero que isso ajude.