F#: Почему типы опции не совместимы с nullable типами?

public static boolean isValidExpression(String expression) {
    Map<Character, Character> openClosePair = new HashMap<Character, Character>();
    openClosePair.put(')', '(');
    openClosePair.put('}', '{');
    openClosePair.put(']', '[');        
    Stack<Character> stack = new Stack<Character>();
    for(char ch : expression.toCharArray()) {
        if(openClosePair.containsKey(ch)) {
            if(stack.pop() != openClosePair.get(ch)) {
                return false;
            }
        } else if(openClosePair.values().contains(ch)) {
            stack.push(ch); 
        }
    }
    return stack.isEmpty();
}
11
задан Brian 3 June 2009 в 20:37
поделиться

4 ответа

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

Nullable<Nullable<int>>

, но у вас может быть

option<option<int>>

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

6
ответ дан 3 December 2019 в 04:33
поделиться

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

1
ответ дан 3 December 2019 в 04:33
поделиться

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

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

0
ответ дан 3 December 2019 в 04:33
поделиться

Из-за выбора представления времени выполнения для 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. Итак, это действительно:

null : string

Но теперь значение времени выполнения null неоднозначно - оно может относиться либо к отсутствию значения, либо к наличию значения null . По этой причине .NET не позволяет создавать System.Nullable .

Сравните это с:

(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 # сможет раскрыть.

17
ответ дан 3 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: