Se você está procurando uma referência funcional e clara à inferência de tipos, sou um pouco parcial em relação à " Inferência de tipos no contexto " de Gundry, McBride e McKinna de 2010 , embora esse possa não ser um bom guia para implementações existentes. .
Acho que parte da resposta é que, além da restrição de valor, realmente não há muita dificuldade em adaptar a inferência do tipo Hindley-Milner a linguagens imperativas: se você define e1; e2
como açúcar sintático para (fn _ => e2) e1
e define while e1 do e2
como açúcar sintático para whiledo e1 (fn () => e2)
, onde whiledo
é um regular função recursiva
fun whiledo g f = if g then (f (); whiledo g f) else ();
tudo funcionará bem, incluindo a inferência de tipo.
Quanto à restrição de valor ser uma técnica especial, gosto da seguinte história; Tenho certeza de que peguei no Karl Crary. Considere o código a seguir, cuja restrição de valor impedirá que você escreva no ML:
let
val x: 'a option ref = ref NONE
in
(x := SOME 5; x := SOME "Hello")
end
Compare-o com o código a seguir, que é totalmente sem problemas:
let
val x: unit -> 'a option ref = fn () => ref NONE
in
(x () := SOME 5; x () := SOME "Hello")
end
Sabemos o que o segundo exemplo faz: ele cria duas novas células ref que contêm NONE
, depois coloca SOME 5
a primeira (an int option ref
), depois coloca SOME "Hello"
a segunda (a string option ref
).
x
x
∀ α . ref ( opção ( α ) )x
Λ α . ref [ α ] ( NENHUM )
Isso sugere que um comportamento "bom" do primeiro exemplo deve se comportar exatamente da mesma maneira que o segundo exemplo - instancia o lambda no nível de tipo duas vezes diferentes. A primeira vez que instanciamos , o que fará x
com int
que seja x [int]
avaliada uma célula de referência em espera NONE
e depois SOME 5
. A segunda vez que instanciar x
com string
, o que diferencia maiúsculas x [string]
para avaliar a uma ( diferente! Exploração) célula de referência NONE
e depois SOME "Hello"
. Esse comportamento é "correto" (seguro para o tipo), mas definitivamente não é o que um programador esperaria, e é por isso que temos a restrição de valor no ML, para evitar que os programadores lidem com esse tipo de comportamento inesperado.
let val x = ref 9 in while !x>0 do (print (Int.toString (!x)); x := !x-1) end
. Então, no nível de uma pergunta de pesquisa, a resposta que você está procurando é "aplicar técnicas desenvolvidas em Caml / SML, incluindo a restrição de valor"?