Якщо ви шукаєте акуратне, функціональне посилання на висновок про тип, я трохи частково ставлюся до "Виводу типу в контексті " Gundry, McBride та McKinna 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 [ α ] ( NONE )
Це наводить на думку про те, що одна "хороша" поведінка першого прикладу повинна вести себе точно так само, як веде другий приклад - інстанціювати лямбда на рівні типу два рази. У перший раз ми створюємо 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, включаючи обмеження значення"?