Тип опции

редактировать

На языках программирования (более того, языках функционального программирования ) и типе теория, тип опции или, возможно, тип - это полиморфный тип, который представляет инкапсуляцию необязательного значения; например, он используется как возвращаемый тип функций, которые могут возвращать или не возвращать значимое значение при их применении. Он состоит из конструктора, который либо пуст (часто называется Noneили Nothing), либо инкапсулирует исходный тип данных A(часто пишется Just Aили Некоторые A).

Отдельная, но связанная концепция вне функционального программирования, которая популярна в объектно-ориентированном программировании, называется типами, допускающими значение NULL (часто выражается как A ?). Основное различие между типами параметров и типами, допускающими значение NULL, заключается в том, что типы параметров поддерживают вложение (Возможно (Может быть A)Может быть A), а типы, допускающие значение NULL, нет (String ??= Строка?).

Содержание

  • 1 Теоретические аспекты
  • 2 Имена и определения
  • 3 Примеры
    • 3.1 Ada
    • 3.2 Scala
    • 3.3 OCaml
    • 3.4 F #
    • 3.5 Haskell
    • 3.6 Swift
    • 3.7 Rust
    • 3.8 Nim
  • 4 См. Также
  • 5 Ссылки

Теоретические аспекты

В теории типов это может быть записано как: А? Знак равно A + 1 {\ displaystyle A ^ {?} = A + 1}A ^ {?} = A + 1 . Это выражает тот факт, что для данного набора значений в A {\ displaystyle A}Aтип опции добавляет ровно одно дополнительное значение (пустое значение) к набору допустимых значений для А {\ displaystyle A}A. Это отражается в программировании тем фактом, что в языках, имеющих помеченные объединения, типы параметров могут быть выражены как помеченное объединение инкапсулированного типа плюс тип блока.

в Curry –Ховард соответствия, типы опций связаны с законом аннигиляции для ∨: x∨1 = 1.

Тип опции также можно рассматривать как коллекцию, содержащий один или ноль элементов.

Тип параметра также является монадой, где:

return = Just - переносит значение в, возможно, Nothing>>= f = Ничего - терпит неудачу, если предыдущая монада терпит неудачу (Just x)>>= f = fx - Успешно, когда обе монады успешны

Монадическая природа типа опции полезна для эффективного отслеживания отказов и ошибок.

Имена и определения

В разных языках программирования тип опции имеет разные имена и определения.

  • В Agda он называется Возможнос вариантами ничегои просто.
  • В C ++ 17 он определяется как класс шаблона std :: optional , optional (), который можно использовать для создания пустой опции. (Может нарушить законы монад из-за большой перегрузки конструкторов.)
  • В C # он определяется как Nullable, но обычно записывается как Т?. (Нарушает законы монад.)
  • В Coq он определяется как Индуктивная опция (A: Тип): Тип: = | Некоторые: А ->вариант А | Нет: вариант A..
  • В Elm он называется Maybeи определяется как type Maybe a = Just a | Ничего.
  • В Haskell он называется Может бытьи определен как данные Может быть a = Ничего | Просто.
  • В Идрисе он определяется как данные. Может быть, а = Ничего | Просто.
  • В Java, начиная с версии 8, он определяется как параметризованный конечный класс Optional. (Нарушает законы монад (карта реализована неправильно).)
  • В Julia он назван Nullable {T}. (Однако это устарело.)
  • В Kotlin он определен как T?. (Нарушает законы монад (не поддерживает вложение).)
  • В OCaml это определено как type 'a option = None | Некоторые из.
  • В Rust они определены как enum Option {None, Some (T)}.
  • В Scala это определяется как запечатанный абстрактный класс Option [+ A], тип, расширенный final case class Some [+ A] (значение: A)и case object None.
  • В Стандартном ML это определено как тип данных 'a option = NONE | НЕКОТОРЫЕ из 'a.
  • В Swift оно определяется как enum Optional {case none, some (T)}, но обычно записывается как T?.

Примеры

Ada

Ada не реализует опционные типы напрямую, однако предоставляет различаемые типы, которые можно использовать для параметризации записи. Для реализации типа Option в качестве дискриминанта используется тип Boolean; В следующем примере представлен универсальный вариант для создания типа параметра из любого неограниченного ограниченного типа:

Универсальный - Любой ограниченный и неограниченный тип. Тип Element_Type является частным; Package Optional_Type - когда дискриминант Has_Element имеет значение true, есть поле элемента, - когда он false, полей нет (отсюда ключевое слово null). Тип Необязательный (Has_Element: Boolean) - это запись, случай Has_Element - это когда False =>Null; когда True =>Element: Element_Type; конец корпуса; конец записи; конец Optional_Type;

Scala

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

объект Main {// Эта функция использует сопоставление с образцом для деконструкции ʻOption`s def computeV1 (opt: Option [Int]): String = opt match {case Some (x) =>s "Значение: $ x" case None =>"Нет значения "} // Эта функция использует встроенный метод` fold` def computeV2 (opt: Option [Int]): String = opt.fold ("No value") (x =>s "Значение: $ x") def main (args: Array [String]): Unit = {// Определяем переменные, которые являются ʻOption`s типа ʻInt` val full = Some (42) val empty: Option [Int] = None // computeV1 ( full) ->Значение: 42 println (s "computeV1 (full) ->$ {computeV1 (full)}") // computeV1 (empty) ->Нет значения println (s "computeV1 (empty) ->$ { computeV1 (empty)} ") // computeV2 (full) ->Значение: 42 println (s" computeV2 (full) ->$ {computeV2 (full)} ") // computeV2 (empty) ->Нет значения println (s "computeV2 (empty) ->$ {computeV2 (empty)}")}}

Два основных способа использования Optionval уе есть. Первый, не самый лучший, - это сопоставление с шаблоном, как в первом примере. Вторая, лучшая практика - это монадический подход, как во втором примере. Таким образом, программа является безопасной, поскольку она не может генерировать исключение или ошибку (например, пытаясь получить значение переменной Option, равное None). Таким образом, он по сути работает как типобезопасная альтернатива нулевому значению.

OCaml

OCaml реализует Optionкак параметризованный вариантный тип. Optionсоздаются и деконструируются следующим образом:

(* Эта функция использует сопоставление с образцом для деконструкции ʻoption`s *) let compute_v1 = function | Некоторый x ->"Значение:" ^ string_of_int x | Нет ->«Нет значения» (* Эта функция использует встроенную функцию `fold` *) let compute_v2 = Option.fold ~ none:" Нет значения "~ some: (fun x ->" Значение: "^ string_of_int x) let () = (* Определить переменные, которые являются ʻoption` типа ʻint` *) let full = Около 42 в let empty = Нет в (* compute_v1 full ->Значение: 42 *) print_endline ( "compute_v1 full ->" ^ compute_v1 full); (* compute_v1 пусто ->Нет значения *) print_endline ("compute_v1 пусто ->" ^ compute_v1 пусто); (* compute_v2 full ->Значение: 42 *) print_endline ("compute_v2 full ->" ^ compute_v2 full); (* compute_v2 empty ->Нет значения *) print_endline ("compute_v2 empty ->" ^ compute_v2 empty)

F #

// Эта функция использует сопоставление с шаблоном для деконструкции ʻoption`s let compute_v1 = function | Некоторые x ->sprintf "Значение:% d" x | Нет ->"Нет значения" // Эта функция использует встроенную функцию `fold` let compute_v2 = Option.fold (fun _ x ->sprintf" Значение:% d "x)" Нет значения "// Определить переменные, которые являются опциями типа ʻint` let full = Some 42 let empty = None // compute_v1 full ->Значение: 42 compute_v1 full |>printfn "compute_v1 full ->% s" // compute_v1 пусто ->Нет значения compute_v1 empty |>printfn "compute_v1 empty ->% s" // compute_v2 full ->Значение: 42 compute_v2 full |>printfn "compute_v2 full ->% s" // compute_v2 empty ->Нет значения compute_v2 empty |>printfn "compute_v2 empty ->% s"

Haskell

- Эта функция использует сопоставление с образцом для деконструкции `Maybe`s computeV1 :: Maybe Int ->String computeV1 (Just x) =" Значение: "++ show x computeV1 Nothing =" No value "- эта функция использует встроенную функцию` foldl` computeV2 :: Maybe Int ->String computeV2 = foldl (\ _ x ->"Значение:" ++ show x) «Нет значения» main :: IO () main = do - Определить переменные, которые являются `Maybe`s типа ʻInt` let fu ll = Всего 42 let empty = Ничего - computeV1 full ->Значение: 42 putStrLn $ "computeV1 full ->" ++ computeV1 full - computeV1 full ->Нет значения putStrLn $ "computeV1 empty ->" ++ computeV1 empty - computeV2 full ->Значение: 42 putStrLn $ "computeV2 full ->" ++ computeV2 full - computeV2 full ->Нет значения putStrLn $ "computeV2 empty ->" ++ computeV2 empty

Swift

// Эта функция использует оператор `switch` для деконструкции ʻOptional`s func computeV1 (_ opt: Int?) ->String {switch opt {case.some (let x): return" Значение: \ (x) "case.none: return" No value "}} // Эта функция использует необязательную привязку для деконструкции ʻOptional`s func computeV2 (_ opt: Int?) ->String {if let x = opt {return" Значение равно : \ (x) "} else {return" No value "}} // Определить переменные, которые являются ʻOptional`s типа ʻInt` let full: Int? = 42 пусть пусто: Int? = nil // computeV1 (full) ->Значение: 42 print ("computeV1 (full) ->\ (computeV1 (full))") // computeV1 (пусто) ->Нет значения print ("computeV1 (пусто) ->\ (computeV1 (empty)) ") // computeV2 (full) ->Значение: 42 print (" computeV2 (full) ->\ (computeV2 (full)) ") // computeV2 (пусто) ->Нет значения print ("computeV2 (empty) ->\ (computeV2 (empty))")

Rust

// Эта функция использует выражение `match` для деконструкции функции ʻOption`s fn compute_v1 (opt: Option ) ->String {match opt {Some (x) =>format! ("Значение: {}", x), None =>"No value".to_owned (),}} // Эта функция использует выражение ʻif let` для деконструкции функции ʻOption`s fn compute_v2 (opt: Option ) ->String {if let Some (x) = opt {format! ("Значение: {}", x)} else {"Нет значения".to_owned ()}} // Эта функция использует встроенный метод `map_or` fn compute_v3 (opt: Option ) ->String {opt.map_or (" No value ".to_owned (), | x | format! ("Значение: {}", x))} fn main () {// Определить переменные, которые являются ʻOption` типа ʻi32` let full = Some (42); пусть пусто: Вариант = Нет; // compute_v1 (full) ->Значение: 42 println! ("compute_v1 (full) ->{}", compute_v1 (full)); // compute_v1 (empty) ->Нет значения println! ("compute_v1 (empty) ->{}", compute_v1 (empty)); // compute_v2 (full) ->Значение: 42 println! ("compute_v2 (full) ->{}", compute_v2 (full)); // compute_v2 (empty) ->Нет значения println! ("compute_v2 (empty) ->{}", compute_v2 (empty)); // compute_v3 (full) ->Значение: 42 println! ("compute_v3 (full) ->{}", compute_v3 (full)); // compute_v3 (empty) ->Нет значения println! ("compute_v3 (empty) ->{}", compute_v3 (empty))}

Параметры импорта Nim

# Эта процедура использует встроенный ʻisSome` и `get` procs, чтобы деконструировать процесс вычисления ʻOption (opt: Option [int]): string = if opt.isSome:" Значение: "$ opt.get else:" No value "# Определить переменные, которые являются ʻOptional 'типа ʻInt` let full = some (42) empty = none (int) # compute (full) ->Значение: 42 echo "compute (full) ->", compute (full) # compute (empty) ->Нет значения echo "compute (empty) ->", compute (empty)

См. также

Ссылки

Последняя правка сделана 2021-06-01 13:37:04
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте