Если вы ищете аккуратную, функциональную ссылку на вывод типов, я немного неравнодушен к «Выводу типов в контексте » Гандри, МакБрайда и МакКинны 2010 года , хотя это может не быть хорошим руководством для любых существующих реализаций. ,
Я думаю, что часть ответа заключается в том, что, помимо ограничения значений, действительно нет особых трудностей в адаптации вывода типа Хиндли-Милнера к императивным языкам: если вы определяете e1; e2как синтаксический сахар для (fn _ => e2) e1и определяете while e1 do e2как синтаксический сахар для whiledo e1 (fn () => e2), где whiledoрегулярный рекурсивная функция
fun whiledo g f = if g then (f (); whiledo g f) else ();
тогда все будет работать нормально, включая вывод типов.
Что касается ограничения стоимости как особой техники, мне нравится следующая история; Я почти уверен, что взял это от Карла Крири. Рассмотрим следующий код, ограничение которого не позволит вам писать в ML:
let
val x: 'a option ref = ref NONE
in
(x := SOME 5; x := SOME "Hello")
end
Сравните это со следующим кодом, который совершенно не проблема:
let
val x: unit -> 'a option ref = fn () => ref NONE
in
(x () := SOME 5; x () := SOME "Hello")
end
Мы знаем, что делает второй пример: он создает две новые ячейки ref, содержащие NONE, затем вставляет SOME 5первую (an int option ref), а затем вставляет SOME "Hello"вторую (a string option ref).
xx∀ α . ref ( опция ( α ) )xΛ α . ref [ α ] ( НЕТ )
Это предполагает, что одно «хорошее» поведение первого примера состоит в том, чтобы вести себя точно так же, как ведет себя второй пример - создавать лямбду на уровне типов два разных раза. В первый раз мы создаем экземпляр xс помощью int, который приведет x [int]к оценке для ссылки на ячейку, NONEа затем SOME 5. Второй раз мы создаем xс string, который будет регистр x [string]для оценки к ( разные! ) Ссылке кювете , NONEа затем SOME "Hello". Такое поведение является «правильным» (типобезопасным), но это определенно не то, чего ожидает программист, и именно поэтому у нас есть ограничение значения в ML, чтобы избежать программистов, имеющих дело с таким неожиданным поведением.
let val x = ref 9 in while !x>0 do (print (Int.toString (!x)); x := !x-1) end. Итак, на уровне исследовательского вопроса, вы ищете ответ «применить методы, разработанные в Caml / SML, включая ограничение стоимости»?