Ответ прост - пустой массив имеет полиморфный тип, потому что он является константой.Это особый случай?Ну, в основном, потому что массив является встроенным типом, который не представлен как ADT, так что да, в typecore.ml
в функции is_nonexpansive есть случай для массива
| Texp_array [] -> true
Однако это не особый случай, это просто вопрос определения, какие синтаксические выражения образуют константы.
Обратите внимание, что в общем случае ослабленное ограничение значений позволяет обобщать выражения, не являющиеся экспансивными (а не только синтаксические константы, как в классическом ограничении значений).Где неэкспансионное выражение - это либо выражение в нормальной форме (т. Е. Константа), либо выражение, вычисление которого не будет иметь никаких наблюдаемых побочных эффектов.В нашем случае [||]
является идеальной константой.
Ограничение значения OCaml еще более смягчено, поскольку оно позволяет обобщать некоторые экспансивные выражения в случае, если переменные типа имеют положительную дисперсию.Но это совсем другая история.
Кроме того, ref None
не пустое значение.Значение ref
само по себе является просто записью с одним изменяемым полем, type 'a ref = {mutable contents : 'a}
, поэтому оно никогда не может быть пустым.Тот факт, что он содержит неизменяемое значение (или ссылается на неизменяемое значение, если хотите), не делает его ни пустым, ни полиморфным.Так же, как [|None|]
, он также не пустой.Это синглтон.Кроме того, последний имеет слабый полиморфный тип.