Если вы ищете аккуратную, функциональную ссылку на вывод типов, я немного неравнодушен к «Выводу типов в контексте » Гандри, МакБрайда и МакКинны 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
).
x
x
∀ α . 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, включая ограничение стоимости»?