Si está buscando una referencia ordenada y funcional para la inferencia de tipos, estoy un poco parcial con respecto a la " Inferencia de tipos en contexto " de Gundry, McBride y McKinna de 2010 , aunque puede que esta no sea una buena guía para ninguna implementación real existente .
Creo que parte de la respuesta es que, más allá de la restricción de valor, realmente no hay tanta dificultad para adaptar la inferencia de tipo Hindley-Milner a los idiomas imperativos: si define e1; e2
como azúcar sintáctico (fn _ => e2) e1
y define while e1 do e2
como azúcar sintáctico para whiledo e1 (fn () => e2)
, ¿dónde whiledo
es un regular función recursiva
fun whiledo g f = if g then (f (); whiledo g f) else ();
entonces todo funcionará bien, incluida la inferencia de tipos.
En cuanto a que la restricción de valor es una técnica especial, me gusta la siguiente historia; Estoy bastante seguro de que lo recogí de Karl Crary. Considere el siguiente código, que la restricción de valor le impedirá escribir en ML:
let
val x: 'a option ref = ref NONE
in
(x := SOME 5; x := SOME "Hello")
end
Compárelo con el siguiente código, que no tiene ningún problema:
let
val x: unit -> 'a option ref = fn () => ref NONE
in
(x () := SOME 5; x () := SOME "Hello")
end
Sabemos lo que hace el segundo ejemplo: crea dos nuevas celdas de referencia que contienen NONE
, luego coloca SOME 5
la primera (a int option ref
), luego coloca SOME "Hello"
la segunda (a string option ref
).
x
x
∀ α .ref ( opción (α))x
Λ α .ref [α]( NINGUNO )
Esto sugeriría que un comportamiento "bueno" del primer ejemplo es comportarse exactamente de la misma manera que el segundo ejemplo: instanciar la lambda de nivel de tipo dos veces diferentes. La primera vez que instanciamos x
con int
, lo que hará que se x [int]
evalúe a una celda de referencia NONE
y luego SOME 5
. La segunda vez que instanciamos x
con string
, lo que hará que se x [string]
evalúe en una celda de referencia ( ¡diferente! ) NONE
Y luego SOME "Hello"
. Este comportamiento es "correcto" (tipo seguro), pero definitivamente no es lo que un programador esperaría, y es por eso que tenemos la restricción de valor en ML, para evitar que los programadores se enfrenten a este tipo inesperado de comportamiento.
let val x = ref 9 in while !x>0 do (print (Int.toString (!x)); x := !x-1) end
. Entonces, a nivel de una pregunta de investigación, ¿la respuesta que está buscando es "aplicar técnicas desarrolladas en Caml / SML, incluida la restricción de valor"?