Я немного читал об ограничении значения в стандартном ML и пытался перевести пример в OCaml, чтобы посмотреть, что он будет делать. Кажется, что OCaml создает эти типы в контекстах, где SML отклоняет программу из-за ограничения значения. Я также видел их в других контекстах, таких как пустые хеш-таблицы, которые еще не были "специализированными" для определенного типа.
http://mlton.org/ValueRestriction
Вот пример отклоненной программы в SML:
val r: 'a option ref = ref NONE
val r1: string option ref = r
val r2: int option ref = r
val () = r1 := SOME "foo"
val v: int = valOf (!r2)
Если вы введете первую строку дословно в SML из Нью-Джерси, вы получите следующая ошибка:
- val r: 'a option ref = ref NONE;
stdIn:1.6-1.33 Error: explicit type variable cannot be generalized at its binding declaration: 'a
Если вы оставляете аннотацию явного типа, вы получаете
- val r = ref NONE
stdIn:1.6-1.18 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val r = ref NONE : ?.X1 option ref
В чем именно этот фиктивный тип? Кажется, он полностью недоступен и не может объединиться ни с чем.
- r := SOME 5;
stdIn:1.2-1.13 Error: operator and operand don't agree [overload conflict]
operator domain: ?.X1 option ref * ?.X1 option
operand: ?.X1 option ref * [int ty] option
in expression:
r := SOME 5
В OCaml, напротив, переменная типа "фиктивный тип" доступна и объединяется с первой, что она может.
# let r : 'a option ref = ref None;;
val r : '_a option ref = {contents = None}
# r := Some 5;;
- : unit = ()
# r ;;
- : int option ref = {contents = Some 5}
Это несколько запутывает и вызывает несколько вопросов.
1) Возможно ли, что соответствующая реализация SML позволяет сделать тип "dummy" выше доступным?
2) Как OCaml сохраняет надежность без ограничения значения? Предоставляет ли он более слабые гарантии, чем SML?
3) Тип '_a option ref
кажется менее полиморфным, чем 'a option ref
. Почему в OCaml не отклоняется let r : 'a option ref = ref None;;
(с явной аннотацией)?