F #: Почему типы опций не совместимы с обнуляемыми типами? - PullRequest
9 голосов
/ 04 июня 2009

Почему типы опций, такие как int, не совместимы с обнуляемыми типами, такими как Nullable?

Я предполагаю, что есть некоторая семантическая причина для различия, но я не могу понять, что это такое.

Опция в F # используется, когда значение может существовать или не существовать. Опция имеет базовый тип и может содержать значение этого типа или может не иметь значения.

http://msdn.microsoft.com/en-us/library/dd233245%28VS.100%29.aspx

Это звучит как Nullable структура.

Ответы [ 4 ]

16 голосов
/ 07 октября 2009

Из-за выбора представления во время выполнения для 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)> и вставляя функции преобразования при необходимости.

6 голосов
/ 04 июня 2009

Два имеют разную семантику. Просто чтобы назвать одно, Nullable - это идемпотентный конструктор данных, который работает только с типами значений, тогда как option - это обычный универсальный тип. Так что вы не можете иметь

Nullable<Nullable<int>>

но вы можете иметь

option<option<int>>

Как правило, хотя есть несколько перекрывающихся сценариев, есть также вещи, которые вы можете делать с одним, но не с другим.

1 голос
/ 04 июня 2009

Ключевым отличием является то, что необходимо проверить тип параметра, чтобы увидеть, имеет ли он значение. Смотрите этот вопрос для хорошего описания его семантики: Как работает тип опции в F #

0 голосов
/ 04 июня 2009

Опять же, это из моего ограниченного понимания, но проблема, вероятно, заключается в том, как каждый из них отображается в IL. «Обнуляемая» структура, вероятно, обрабатывается немного иначе, чем тип параметра.

Вы обнаружите, что взаимодействие между различными языками .Net действительно сводится к тому, как визуализируется IL. Большую часть времени это работает просто отлично, но иногда это вызывает проблемы. ( проверить это ). Как раз тогда, когда вы думали, что можно доверять уровню абстракции. :)

...