Jeśli szukasz zgrabnego, funkcjonalnego odniesienia do wnioskowania o typie, jestem trochę stronnikiem Gundry, McBride i McKinny z „ Inferencji typów w kontekście ”, choć może to nie być dobrym przewodnikiem po istniejących istniejących implementacjach .
Myślę, że częścią odpowiedzi jest to, że poza ograniczeniem wartości naprawdę nie ma tak dużych trudności w dostosowaniu wnioskowania typu Hindley-Milner do języków imperatywnych: jeśli zdefiniujesz e1; e2jako cukier składniowy (fn _ => e2) e1i zdefiniujesz while e1 do e2jako cukier syntaktyczny dla whiledo e1 (fn () => e2), gdzie whiledojest regularny funkcja rekurencyjna
fun whiledo g f = if g then (f (); whiledo g f) else ();
wtedy wszystko będzie działać poprawnie, w tym wnioskowanie typu.
Jeśli chodzi o ograniczenie wartości będące specjalną techniką, podoba mi się następująca historia; Jestem prawie pewien, że odebrałem go od Karla Crary'ego. Rozważ następujący kod, którego ograniczenie wartości nie pozwoli Ci pisać w ML:
let
val x: 'a option ref = ref NONE
in
(x := SOME 5; x := SOME "Hello")
end
Porównaj go z następującym kodem, który jest całkowicie bezproblemowy:
let
val x: unit -> 'a option ref = fn () => ref NONE
in
(x () := SOME 5; x () := SOME "Hello")
end
Wiemy, co robi drugi przykład: tworzy dwie nowe komórki ref zawierające NONE, następnie wstawia SOME 5pierwszą (an int option ref), a następnie wstawia SOME "Hello"drugą (a string option ref).
xx∀ α . ref ( opcja ( α ) )xΛ α . ref [ α ] ( BRAK )
Sugerowałoby to, że jednym „dobrym” zachowaniem w pierwszym przykładzie jest zachowanie dokładnie tak samo, jak w drugim przykładzie - utworzenie wystąpienia lambda na poziomie typu dwa razy. Za pierwszym razem instancję xz int, który spowoduje, że x [int]do oceny do gospodarstwa komórek odniesienia NONE, a następnie SOME 5. Po raz drugi wystąpienia xz string, które będą rozróżniane x [string]ocenić na ( inaczej! Gospodarstwie) komórek odniesienia NONE, a następnie SOME "Hello". To zachowanie jest „poprawne” (bezpieczne dla typu), ale zdecydowanie nie jest to, czego programista by się spodziewał, i dlatego mamy ograniczenie wartości w ML, aby uniknąć programistów radzących sobie z tym nieoczekiwanym zachowaniem.
let val x = ref 9 in while !x>0 do (print (Int.toString (!x)); x := !x-1) end. Więc na poziomie pytania badawczego, czy szukasz odpowiedzi „zastosuj techniki opracowane w Caml / SML, w tym ograniczenie wartości”?