Si vous recherchez une référence fonctionnelle et soignée à l'inférence de type, je suis un peu partial à Gundry, McBride et McKinna 2010 " Type Inference in Context ", bien que cela ne soit pas un bon guide pour les implémentations existantes réelles .
Je pense qu'une partie de la réponse est que, au-delà de la restriction de valeur, il n'y a vraiment pas beaucoup de difficulté à adapter l'inférence de type Hindley-Milner aux langues impératives: si vous définissez e1; e2
comme sucre syntaxique pour (fn _ => e2) e1
et définissez while e1 do e2
comme sucre syntaxique pour whiledo e1 (fn () => e2)
, où whiledo
est un régulier fonction récursive
fun whiledo g f = if g then (f (); whiledo g f) else ();
alors tout fonctionnera bien, y compris l' inférence de type.
Quant à la restriction de valeur étant une technique spéciale, j'aime l'histoire suivante; Je suis presque sûr de l'avoir récupéré auprès de Karl Crary. Considérez le code suivant, dont la restriction de valeur vous empêchera d'écrire en ML:
let
val x: 'a option ref = ref NONE
in
(x := SOME 5; x := SOME "Hello")
end
Comparez-le au code suivant, ce qui ne pose aucun problème:
let
val x: unit -> 'a option ref = fn () => ref NONE
in
(x () := SOME 5; x () := SOME "Hello")
end
Nous savons ce que fait le deuxième exemple: il crée deux nouvelles cellules ref contenant NONE
, puis met SOME 5
dans le premier (an int option ref
), puis met SOME "Hello"
dans le second (a string option ref
).
Mais réfléchissez au premier exemple en termes de représentation x
dans le système F (le lambda-calcul polymorphe). Dans un tel paramètre, x
serait une valeur de type " ", ce qui signifie que, comme terme, la valeur de doit être un (type) lambda: "∀α.ref(option(α))x
Λα.ref[α](NONE) ".
Cela suggérerait qu'un «bon» comportement du premier exemple consiste à se comporter exactement de la même manière que le deuxième exemple - instancier le lambda de niveau type à deux moments différents. La première fois que nous instancions x
avec int
, ce qui entraînera x [int]
d'évaluer une tenue de cellule de référence NONE
puis SOME 5
. La deuxième fois, nous instancions x
avec string
, ce qui sera le cas x [string]
pour évaluer une cellule de référence ( différente! ) NONE
Et ensuite SOME "Hello"
. Ce comportement est "correct" (type-safe), mais ce n'est certainement pas ce à quoi un programmeur s'attendrait, et c'est pourquoi nous avons la restriction de valeur en ML, pour éviter aux programmeurs de gérer ce type de comportement inattendu.
let val x = ref 9 in while !x>0 do (print (Int.toString (!x)); x := !x-1) end
. Donc, au niveau d'une question de recherche, la réponse que vous recherchez est-elle «d'appliquer des techniques développées en Caml / SML, y compris la restriction de valeur»?