Тип варианта - Option type

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

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

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

В теория типов, это можно записать как: . Это выражает тот факт, что для данного набора значений в , тип опции добавляет ровно одно дополнительное значение (пустое значение) к набору допустимых значений для . Это отражается в программировании тем фактом, что в языках, имеющих отмеченные союзы, типы параметров могут быть выражены как помеченное объединение инкапсулированного типа плюс тип единицы.[1]

в Переписка Карри – Ховарда, типы опционов относятся к закон аннигиляции для ∨: x∨1 = 1.[как? ]

Тип опциона также можно рассматривать как коллекция содержащий один или ноль элементов.[оригинальное исследование? ]

Тип опциона также является монада куда:[2]

возвращаться = Только - Оборачивает ценность в возможноНичего  >>= ж = Ничего - Не работает, если предыдущая монада не работает(Только Икс) >>= ж = ж Икс     - Успешно, когда обе монады успешны

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

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

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

  • В Агда, это называется Может быть с вариантами ничего и просто.
  • В C ++ 17 он определяется как класс шаблона стандартное::необязательный<Т>, необязательный() можно использовать для создания пустой опции. (Может нарушить законы монад из-за большой перегрузки конструкторов.)
  • В C #, он определяется как Обнуляемый<Т> но обычно пишется как Т?. (Нарушает законы монад.)
  • В Coq, он определяется как Индуктивный вариант (А:Тип) : Тип := | Немного : А -> вариант А | Никто : вариант А..
  • В Вяз, это называется Может быть, и определяется как тип Может быть а = Только а | Ничего.[4]
  • В Haskell, это называется Может быть, и определяется как данные Может быть а = Ничего | Только а.
  • В Идрис, он определяется как данные Может быть а = Ничего | Только а.
  • В Ява, начиная с версии 8, он определяется как параметризованный конечный класс Необязательный<Т>. (Нарушает законы монад (некорректно реализована карта).)
  • В Юля, это называется Обнуляемый{Т}. (Однако это устарело.[5])
  • В Котлин, он определяется как Т?.[6] (Нарушает законы монад (не поддерживает вложение).)
  • В OCaml, он определяется как тип 'а вариант = Никто | Немного из 'а.
  • В Perl 6, это значение по умолчанию, но вы можете добавить :D «смайлик», чтобы выбрать тип без опций. (Нарушает законы монад (не поддерживает вложение.))
  • В Ржавчина, он определяется как перечислить Вариант<Т>{Никто,Немного(Т)}.
  • В Scala, он определяется как запечатанный Абстрактные учебный класс Вариант[+ А], тип, расширенный окончательный дело учебный класс Немного[+ А](ценить: А) и дело объект Никто.
  • В Стандартный ML, он определяется как тип данных вариант = НИКТО | НЕМНОГО из .
  • В Быстрый, он определяется как перечислить Необязательный<Т> { дело никто, немного(Т) } но обычно пишется как Т?.[7]

Примеры

Ада

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

Общий  - Любой ограниченный и неограниченный тип.  Тип Element_Type является частный;Упаковка Optional_Type является  - Когда дискриминант Has_Element истинен, есть поле элемента,  - когда оно ложно, полей нет (отсюда и ключевое слово null).  Тип Необязательный( Has_Element : Булево ) является записывать    дело Has_Element является      когда Ложь => Ноль;      когда Истинный  => Элемент : Element_Type;    конец дело;  конец записи;конец Optional_Type;

Scala

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

объект Главный {  // Эта функция использует сопоставление с образцом для деконструкции `Option`s  def computeV1(выбрать: Вариант[Int]): Нить =    выбрать матч {      дело Немного(Икс) => s "Значение: $ x"      дело Никто    => "Неважно"    }  // Эта функция использует встроенный метод `fold`  def computeV2(выбрать: Вариант[Int]): Нить =    выбрать.складывать("Неважно")(Икс => s "Значение: $ x")  def главный(аргументы: Множество[Нить]): Единица измерения = {    // Определяем переменные, которые являются `Option`s типа` Int`    вал полный = Немного(42)    вал пустой: Вариант[Int] = Никто    // computeV1 (полный) -> Значение: 42    println(s "computeV1 (полный) ->${computeV1(полный)}")    // computeV1 (пусто) -> Нет значения    println(s "computeV1 (пусто) ->${computeV1(пустой)}")    // computeV2 (полный) -> Значение: 42    println(s "computeV2 (полный) ->${computeV2(полный)}")    // computeV2 (пусто) -> Нет значения    println(s "computeV2 (пусто) ->${computeV2(пустой)}")  }}

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

OCaml

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

(* Эта функция использует сопоставление с образцом для деконструкции `option`s *)позволять compute_v1 = функция  | Немного Икс -> "Значение:" ^ string_of_int Икс  | Никто -> "Неважно"(* Эта функция использует встроенную функцию `fold` *)позволять compute_v2 =  Вариант.складывать ~никто:"Неважно" ~немного:(весело Икс -> "Значение:" ^ string_of_int Икс)позволять () =  (* Определите переменные, которые являются `option`s типа` int` *)  позволять полный = Немного 42 в  позволять пустой = Никто в  (* compute_v1 full -> Значение: 42 *)  print_endline ("compute_v1 full ->" ^ compute_v1 полный);  (* compute_v1 пусто -> Нет значения *)  print_endline ("compute_v1 пусто ->" ^ compute_v1 пустой);  (* compute_v2 full -> Значение: 42 *)  print_endline ("compute_v2 full ->" ^ compute_v2 полный);  (* compute_v2 пусто -> Нет значения *)  print_endline ("compute_v2 пусто ->" ^ compute_v2 пустой)

F #

// Эта функция использует сопоставление с образцом для деконструкции `option`sпозволять compute_v1 = функция    | Немного Икс -> спринт "Значение:% d" Икс    | Никто -> "Неважно"// Эта функция использует встроенную функцию `fold`позволять compute_v2 =    Вариант.складывать (весело _ Икс -> спринт "Значение:% d" Икс) "Неважно"// Определяем переменные, которые являются `option`s типа` int`позволять полный = Немного 42позволять пустой = Никто// compute_v1 full -> Значение: 42compute_v1 полный |> printfn "compute_v1 full ->% s"// compute_v1 пусто -> Нет значенияcompute_v1 пустой |> printfn "compute_v1 пусто ->% s"// compute_v2 full -> Значение: 42compute_v2 полный |> printfn "compute_v2 full ->% s"// compute_v2 пусто -> Нет значенияcompute_v2 пустой |> printfn "compute_v2 пусто ->% s"

Haskell

- Эта функция использует сопоставление с образцом для деконструкции `Maybe`scomputeV1 :: Может быть Int -> НитьcomputeV1 (Только Икс) = "Значение:" ++ Показать ИксcomputeV1 Ничего  = "Неважно"- Эта функция использует встроенную функцию `foldl`computeV2 :: Может быть Int -> НитьcomputeV2 = складка (_ Икс -> "Значение:" ++ Показать Икс) "Неважно"главный :: IO ()главный = делать    - Определите переменные, которые являются `Maybe`s типа` Int`    позволять полный = Только 42    позволять пустой = Ничего    - computeV1 full -> Значение: 42    putStrLn $ "computeV1 full ->" ++ computeV1 полный    - computeV1 full -> Нет значения    putStrLn $ "computeV1 пусто ->" ++ computeV1 пустой    - computeV2 full -> Значение: 42    putStrLn $ "computeV2 full ->" ++ computeV2 полный    - computeV2 full -> Нет значения    putStrLn $ "computeV2 пусто ->" ++ computeV2 пустой

Быстрый

// Эта функция использует оператор switch для деконструкции Optional`sfunc computeV1(_ выбрать: Int?) -> Нить {    выключатель выбрать {    дело .немного(позволять Икс):        возвращаться "Значение: (Икс)"    дело .никто:        возвращаться "Неважно"    }}// Эта функция использует необязательную привязку для деконструкции `Optional`sfunc computeV2(_ выбрать: Int?) -> Нить {    если позволять Икс = выбрать {        возвращаться "Значение: (Икс)"    } еще {        возвращаться "Неважно"    }}// Определяем переменные, которые являются `Optional`s типа` Int`позволять полный: Int? = 42позволять пустой: Int? = ноль// computeV1 (полный) -> Значение: 42Распечатать("computeV1 (полный) ->(computeV1(полный))")// computeV1 (пусто) -> Нет значенияРаспечатать("computeV1 (пусто) ->(computeV1(пустой))")// computeV2 (полный) -> Значение: 42Распечатать("computeV2 (полный) ->(computeV2(полный))")// computeV2 (пусто) -> Нет значенияРаспечатать("computeV2 (пусто) ->(computeV2(пустой))")

Ржавчина

// Эта функция использует выражение `match` для деконструкции` Option`sfn compute_v1(выбрать: &Вариант<i32>)-> Нить {матчвыбрать{Немного(Икс)=>формат!("Значение: {}",Икс),Никто=>"Неважно".to_owned(),}}// Эта функция использует выражение if let для деконструкции Option`sfn compute_v2(выбрать: &Вариант<i32>)-> Нить {еслипозволятьНемного(Икс)=выбрать{формат!("Значение: {}",Икс)}еще{"Неважно".to_owned()}}// Эта функция использует встроенный метод map_orfn compute_v3(выбрать: &Вариант<i32>)-> Нить {выбрать.map_or("Неважно".to_owned(),|Икс|формат!("Значение: {}",Икс))}fn главный(){// Определяем переменные, которые являются `Option`s типа` i32`позволятьполный=Немного(42);позволятьпустой: Вариант<i32>=Никто;// compute_v1 (& full) -> Значение: 42println!("compute_v1 (& полный) -> {}",compute_v1(&полный));// compute_v1 (& пустой) -> Нет значенияprintln!("compute_v1 (& пустой) -> {}",compute_v1(&пустой));// compute_v2 (& full) -> Значение: 42println!("compute_v2 (& полный) -> {}",compute_v2(&полный));// compute_v2 (& пустой) -> Нет значенияprintln!("compute_v2 (& пустой) -> {}",compute_v2(&пустой));// compute_v3 (& full) -> Значение: 42println!("compute_v3 (& полный) -> {}",compute_v3(&полный));// compute_v3 (& пустой) -> Нет значенияprintln!("compute_v3 (& пустой) -> {}",compute_v3(&пустой))}

Ним

импорт опции# Эта процедура использует встроенные процедуры `isSome` и` get` для деконструкции `Option`sproc вычислить(выбрать: Вариант[int]): нить =  если выбрать.isSome:    «Ценность:» & $выбрать.получать  еще:    "Неважно"# Определить переменные, которые являются `Optional`s типа` Int`позволять  полный = немного(42)  пустой = никто(int)# compute (full) -> Значение: 42эхо "вычислить (полный) ->", вычислить(полный)# вычислить (пусто) -> Нет значенияэхо "вычислить (пусто) ->", вычислить(пустой)

Смотрите также

Рекомендации

  1. ^ Милевски, Бартош (13 января 2015). «Простые алгебраические типы данных». Кафе Бартоша Милевски для программирования. Типы сумм. «Мы могли бы закодировать Maybe как: data Maybe a = Either () a». В архиве из оригинала на 18.08.2019. Получено 2019-08-18.
  2. ^ "Горсть монад - выучите Haskell на благо!". www.learnyouahaskell.com. Получено 2019-08-18.
  3. ^ Хаттон, Грэм (25 ноября, 2017). "Что такое монада?". Любитель компьютеров Youtube. Получено 18 августа, 2019.
  4. ^ "Может быть · Знакомство с вязом". guide.elm-lang.org.
  5. ^ «Примечания к выпуску Julia v0.7.0 · Язык Julia». docs.julialang.org.
  6. ^ "Null Safety - язык программирования Kotlin". Получено 2016-08-01.
  7. ^ «Документация для разработчиков Apple». developer.apple.com. Получено 2020-09-06.
  8. ^ Мартин Одерский; Lex Spoon; Билл Веннерс (2008). Программирование на Scala. Artima Inc., стр. 282–284. ISBN  978-0-9815316-0-1. Получено 6 сентября 2011.