Из-за выбора представления во время выполнения для System.Nullable<'T>
.
Nullable пытается представить отсутствие значений нулевым указателем и представить значения указателями на эти значения.
(new System.Nullable<int>() :> obj) = null
|> printfn "%b" // true
(new System.Nullable<int>(1) :> obj).GetType().Name
|> printfn "%s" // Int32
Теперь рассмотрим строки. К сожалению, строки обнуляются. Так что это действительно:
null : string
Но теперь значение null
времени выполнения неоднозначно - оно может относиться либо к отсутствию значения, либо к наличию значения null
. По этой причине .NET не позволяет создавать System.Nullable<string>
.
Сравните это с:
(Some (null : string) :> obj).GetType().Name
|> printfn "%s" // Option`1
При этом можно определить биекцию:
let optionOfNullable (a : System.Nullable<'T>) =
if a.HasValue then
Some a.Value
else
None
let nullableOfOption = function
| None -> new System.Nullable<_>()
| Some x -> new System.Nullable<_>(x)
Если вы наблюдаете типы, эти функции ограничивают 'T
структурой и имеют конструктор с нулевым аргументом. Поэтому, возможно, F # -компилятор мог бы выставлять .NET-функции, получающие / возвращающие Nullable<'T>
, подставляя его для Option<'T where 'T : struct and 'T : (new : unit -> 'T)>
и вставляя функции преобразования при необходимости.