Как работает тип опции в F # - PullRequest
9 голосов
/ 08 марта 2009

Итак, я читал книгу Expert F # от Apress, в основном используя ее в качестве справочной при создании библиотеки F # для игрушек, но есть одна вещь, которую я не смог понять, это тип «Option».

Как это работает и как оно используется в реальном мире?

Ответы [ 6 ]

20 голосов
/ 08 марта 2009

Тип параметра не менее аналогичен Nullable<T> и ссылочным типам в C #. Значением типа Option<T> является либо None, что означает отсутствие инкапсулированного значения, либо Some с конкретным значением T. Это похоже на то, как Nullable<int> в C # равно либо , нулевое значение, или имеет ассоциированный int, а String в C # равно 1015 * либо пустая ссылка, или относится к объекту String.

Когда вы используете значение параметра, вы обычно указываете два пути - один для случая, когда является ассоциированным значением, и один, где не . Другими словами, этот код:

let stringLength (str:Option<string>) =
  match str with
  | Some(v) -> v.Length
  | None -> -1

похож на:

int StringLength(string str)
{
    if (str != null)
    {
        return str.Length;
    }
    else
    {
        return -1;
    }
}

Я полагаю, что общая идея состоит в том, что принуждает вас (ну, почти) обрабатывать случай "без связанного значения / объекта", делает ваш код более устойчивым.

5 голосов
/ 08 марта 2009

Один из лучших примеров реального использования - шаблон TryParse в .Net. Смотрите первую половину

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry

для обсуждения.

4 голосов
/ 08 марта 2009

Используется, когда функция или метод должны «возможно» или «опционально» возвращать значение. В C # вы, вероятно, вернете null или вернете Null Object или, возможно, Nullable для типов значений.

Недостатком возврата null (наиболее распространенный случай) является то, что он небезопасен: null является экземпляром всех типов, так что вы попадаете во все виды проблемных нулевых ссылочных ситуаций позже.

Тип Option - это так называемый исключенный тип объединения с двумя конструкторами: None и Some a. Ничто явно не указывает на то, что у вас нет значения. По сути, это обобщенный шаблон Null Object.

3 голосов
/ 08 марта 2009

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

 val x : int option ref = None 

Затем вы можете позже обновить x до Some v. Вы используете его с оператором match, например,

 match !x with (* dereference x *)
    None -> (* No value, do something *)
 |  Some v -> (* Value v, do something else *)
1 голос
/ 09 марта 2009

Чтобы добавить к другим ответам, тип Option не является чем-то особенным - это просто еще один различимый союз. Вы можете определить это самостоятельно в одной строке:

type 'a Option = None | Some of 'a

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

0 голосов
/ 18 мая 2009

Функциональный шаблон с использованием типа параметра:

Когда вам нужно изменить части рекурсивной структуры данных, такие как дерево или список, Вы захотите использовать как можно большую часть существующей структуры данных. Тип опции могу помочь вам с этим Эти две функции заменяют все вхождения числа 5 на 7, но первый копирует все дерево. Второй нет.

type Tree = Leaf of int
      | Node of Tree * Tree

let rec replace_no_sharing tree =
    match tree with
    | Leaf 5      -> Leaf 7
    | Leaf x      -> Leaf x
    | Node (a, b) -> Node (replace_no_sharing a, replace_no_sharing b)

let replace_with_sharing tree =
    let rec replace_option tree =
        match tree with
        | Leaf 5      -> Leaf 7 |> Some
        | Leaf x      -> None
        | Node (a, b) -> match replace_option a, replace_option b with
                         | None, None     -> None
                         | Some a, Some b -> Node (a, b) |> Some
                         | Some a, None   -> Node (a, b) |> Some
                         | None, Some b   -> Node (a, b) |> Some
    match replace_option tree with
    | None      -> tree
    | Some tree -> tree

Это может быть необязательно во всех случаях, но это хорошая техника, которую нужно знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...