В языках программирования (особенно в языках функционального программирования ) и теории типов тип опции или, возможно, тип — это полиморфный тип , который представляет собой инкапсуляцию необязательного значения; например, он используется как возвращаемый тип функций, которые могут возвращать или не возвращать значимое значение при их применении. Он состоит из конструктора, который либо пуст (часто с именем None
или Nothing
), либо инкапсулирует исходный тип данных A
(часто написан Just A
или Some A
).
Отдельная, но связанная концепция вне функционального программирования, которая популярна в объектно-ориентированном программировании , называется типами, допускающими значение NULL (часто обозначаемых как A?
). Основное различие между типами опций и типами, допускающими значение NULL, заключается в том, что типы опций поддерживают вложенность (например, Maybe (Maybe String)
≠ Maybe String
), а типы, допускающие значение NULL, — нет (например, String??
= String?
).
В теории типов это можно записать так: . Это выражает тот факт, что для данного набора значений в тип опции добавляет ровно одно дополнительное значение (пустое значение) к набору допустимых значений для . В программировании это отражается в том факте, что в языках, имеющих теговые объединения , типы опций могут быть выражены как тегированное объединение инкапсулированного типа плюс тип единицы . [1]
В соответствии Карри–Ховарда типы опционов связаны с законом уничтожения для ∨: x∨1=1. [ как? ]
Тип опции также можно рассматривать как коллекцию , содержащую один или ноль элементов. [ оригинальное исследование? ]
Тип опции также является монадой , где: [2]
return = Just — оборачивает значение в возможное значение. Nothing >>= f = Nothing — завершается неудачей, если предыдущая монада потерпела неудачу ( просто x ) >>= f = f x — завершается успешно, если обе монады успешны
Монадическая природа типа параметра полезна для эффективного отслеживания сбоев и ошибок. [3]
В Agda тип опции обозначается Maybe
вариантами nothing
и .just a
Начиная с C++17, тип опции определяется в стандартной библиотеке как .template<typename T> std::optional<T>
В Coq тип опции определяется как .Inductive option (A:Type) : Type := | Some : A -> option A | None : option A.
В Elm тип опции определяется как . [4]type Maybe a = Just a | Nothing
пусть showValue = Option . fold ( fun _ x -> sprintf "Значение: %d" x ) "Нет значения" пусть полный = около 42, пусть пустой = нет showValue full |> printfn "showValue full -> %s" showValue пустой |> printfn "showValue пустой -> %s"
showValue полное -> Значение: 42 showValue пустое -> Нет значения
В Haskell тип опции определяется как . [5]data Maybe a = Nothing | Just a
showValue :: Maybe Int -> String showValue = foldl ( \ _ x -> "Значение: " ++ show x ) "Нет значения" main :: IO () main = do let full = всего 42 let пустой = ничего putStrLn $ "showValue полное -> " ++ showValue полное putStrLn $ "showValue пустое -> " ++ showValue пустое
showValue полное -> Значение: 42 showValue пустое -> Нет значения
В Idris тип опции определяется как .data Maybe a = Nothing | Just a
showValue : Maybe Int -> String
showValue = foldl (\ _ , x => "Значение равно " ++ show x ) "Нет значения" main : IO ()
main = do let full = всего 42 let пустой = ничего putStrLn $ "showValue полное -> " ++ showValue полное putStrLn $ "showValue пустое -> " ++ showValue пустое
showValue полное -> Значение: 42 showValue пустое -> Нет значения
импортировать стандартные параметры / опции proc showValue ( opt : Option [ int ] ): строка = opt . map ( proc ( x : int ): string = "Значение: " & $ x ). получить ( «Нет значения» ) пусть полный = некоторые ( 42 ) пустой = нет ( int ) echo "showValue(full) -> " , showValue ( full ) echo "showValue(empty) -> " , showValue ( пусто )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В OCaml тип параметра определяется как . [6]type 'a option = None | Some of 'a
пусть show_value = Вариант . свернуть ~ нет : «Нет значения» ~ некоторые :( fun x -> «Значение: » ^ string_of_int x )let () = let full = около 42 , let пустой = нет в print_endline ( "show_value полное -> " ^ show_value полное ); print_endline ( «show_value пусто ->» ^ show_value пусто )
show_value полное -> Значение: 42 show_value пустое -> Нет значения
В Rust тип опции определяется как . [7]enum Option<T> { None, Some(T) }
fn show_value ( opt : Option <i32> ) - > String { opt . _ map_or ( "Нет значения" . to_owned (), | x | format! ( "Значение: {}" , x )) } fn main () { let full = Some ( 42 ); пусть пусто = Нет ; распечататьлн! ( "show_value(full) -> {}" , show_value ( full )); распечататьлн! ( "show_value(empty) -> {}" , show_value ( пусто )); }
show_value(full) -> Значение: 42 show_value(empty) -> Нет значения
В Scala тип опции определяется как тип, расширенный с помощью и .sealed abstract class Option[+A]
final case class Some[+A](value: A)
case object None
object Main : def showValue ( opt : Option [ Int ]): String = opt . fold ( "Нет значения" )( x => s"Значение: $ x " ) def main ( args : Array [ String ]): Единица = значение полное = Некоторые ( 42 ) значение пустое = Нет println ( s"showValue(full) -> ${ showValue ( full ) } " ) println ( s"showValue(empty) -> ${ showValue ( empty ) } " )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В Standard ML тип опции определяется как .datatype 'a option = NONE | SOME of 'a
В Swift тип опции определяется как, но обычно записывается как . [8]enum Optional<T> { case none, some(T) }
T?
func showValue ( _ opt : Int ?) -> String { return opt . map { "Значение: \( $0 ) " } ?? "Неважно" }пусть полный = 42 пусть пустой : Int ? = нольprint ( "showValue(full) -> \( showValue ( full )) " ) print ( "showValue(empty) -> \( showValue ( empty )) " )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В Zig добавьте ? перед именем типа хотелось бы ?i32
сделать его необязательным типом.
Полезная нагрузка n может быть зафиксирована в операторе if или while , например , и предложение else оценивается, если оно есть .if (opt) |n| { ... } else { ... }
null
const std = @import ( "std" ); fn showValue ( распределитель : std . mem . Распределитель , опция : ? i32 ) ! [] u8 { return if ( opt ) | п | стандарт . фмт . allocPrint ( распределитель , «Значение: {}» , .{ n }) else распределитель . dupe ( u8 , «Нет значения» ); } паб fn main () ! void { // Настраиваем распределитель и предупреждаем, если мы забудем освободить память. вар ГПА = станд . куча . GeneralPurposeAllocator (.{}){}; отложить станд . отладка . утверждать ( gpa . deinit () == . ок ); константный распределитель = gpa . распределитель (); // Подготавливаем стандартный поток вывода. константный стандартный вывод = стандартный . ио . getStdOut (). писатель (); // Выполним наш пример. константа полная = 42 ; константа пустая = ноль ; const full_msg = попробуйте showValue ( распределитель , полный ); отложить распределитель . бесплатно ( full_msg ); попробуйте стандартный вывод . print ( "showValue(allocator, full) -> {s} \n " , .{ full_msg }); const пустой_msg = попробуйте showValue ( распределитель , пустой ); отложить распределитель . бесплатно ( empty_msg ); попробуйте стандартный вывод . print ( "showValue(распределитель, пустой) -> {s} \n " , .{ пустой_msg }); }
showValue(распределитель, полный) -> Значение: 42 showValue(распределитель, пустой) -> Нет значения