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; e2
jako cukier składniowy (fn _ => e2) e1
i zdefiniujesz while e1 do e2
jako cukier syntaktyczny dla whiledo e1 (fn () => e2)
, gdzie whiledo
jest 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 5
pierwszą (an int option ref
), a następnie wstawia SOME "Hello"
drugą (a string option ref
).
x
x
∀ α . 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ę x
z 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 x
z 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”?