Опция OCaml

Я новичок в OCaml, я пытаюсь понять, как вы должны получать значение из опции "a". Согласно документу http://ocaml-lib.sourceforge.net/doc/Option.html, есть функция get типа 'a option → ' a, которая делает то, что я хочу. но когда я печатаю:

# let z = Some 3;;
val z : int option = Some 3
# get z;;
Error: Unbound value get
# Option.get z;;
Error: Unbound module Option

Почему это не работает?

Ответ 1

Традиционный способ получения значения внутри любого конструктора в OCaml - это сопоставление с образцом. Согласование шаблонов является частью OCaml, которая может отличаться от того, что вы уже видели на других языках, поэтому я бы рекомендовал вам не просто писать программы так, как вы привыкли (например, обойти проблему с ocaml-lib), но попробуйте и посмотрите, нравится ли вам это.

let contents = 
   match z with
   Some c -> c;;

Переменная contents назначается 3, но вы получаете предупреждение:

Предупреждение 8: это сопоставление шаблонов не является исчерпывающим. Вот пример значения, которое не соответствует: None

В общем случае вы не будете знать, что выражение, которое вы хотите просмотреть внутри, обязательно является Some c. Причина выбора типа опции обычно такова, что иногда это значение может быть None. Здесь компилятор напоминает вам, что вы не обрабатываете один из возможных случаев.

Вы можете совпадать с шаблоном "по глубине", и компилятор по-прежнему будет проверять полноту. Рассмотрим эту функцию, которая принимает (int option) option:

let f x =
  match x with
  Some (Some c) -> c
  | None -> 0
  ;;

Здесь вы забыли случай Some (None), и компилятор говорит вам об этом:

Предупреждение 8: это сопоставление шаблонов не является исчерпывающим. Вот пример значения, которое не соответствует: Some None

Ответ 2

Обычный способ сделать это с помощью сопоставления с образцом.

# let x = Some 4;;
val x : int option = Some 4

# match x with
  | None -> Printf.printf "saw nothing at all\n"
  | Some v -> Printf.printf "saw %d\n" v;;
saw 4
- : unit = ()

Вы можете написать свою собственную функцию get (хотя вам нужно решить что вы хотите сделать, когда значение None).

Ответ 3

Вы должны прислушаться к приведенным выше советам плакатов относительно безопасности типов, но также помните, что небезопасные функции, такие как Option.get(которые доступны в батареях кстати), обычно суффикс с exn. Если вам интересно, как реализовать Option.get или Option.get_exn, то:

let get_exn = function
  | Some x -> x
  | None   -> raise (Invalid_argument "Option.get")