В языках программирования (особенно функциональных языках программирования ) и теории типов , опционный тип или, возможно, тип — это полиморфный тип , представляющий инкапсуляцию необязательного значения; например, он используется как возвращаемый тип функций, которые могут или не могут возвращать осмысленное значение при применении. Он состоит из конструктора, который либо пуст (часто именуется None
или Nothing
), либо инкапсулирует исходный тип данных A
(часто пишется Just A
или Some A
).
Отдельная, но связанная концепция за пределами функционального программирования, которая популярна в объектно-ориентированном программировании , называется nullable types (часто обозначается как A?
). Основное различие между option types и nullable types заключается в том, что option types поддерживают вложенность (например, Maybe (Maybe String)
≠ Maybe String
), в то время как nullable types — нет (например, String??
= String?
).
В теории типов это можно записать как: . Это выражает тот факт, что для заданного набора значений в тип опции добавляет ровно одно дополнительное значение (пустое значение) к набору допустимых значений для . Это отражается в программировании тем фактом, что в языках, имеющих тегированные объединения , типы опций могут быть выражены как тегированное объединение инкапсулированного типа плюс тип единицы . [1]
В соответствии с Карри–Ховардом типы опционов связаны с законом уничтожения для ∨: x∨1=1. [ как? ]
Тип параметра также можно рассматривать как коллекцию, содержащую либо один, либо ноль элементов. [ оригинальное исследование? ]
Тип параметра также является монадой , где: [2]
return = Just — Оборачивает значение в Maybe Nothing >>= f = Nothing -- Ошибка, если предыдущая монада не удалась ( Just x ) >>= f = f x -- Успешно, если обе монады успешны
Монадическая природа типа option полезна для эффективного отслеживания сбоев и ошибок. [3]
В Agda тип опции именуется Maybe
с помощью вариантов nothing
и .just a
В ATS тип опции определяется как
datatype option_t0ype_bool_type ( a : t @ ype +, bool ) = | Некоторые ( a , true ) из a | Ни один ( a , false ) stadef option = option_t0ype_bool_type typedef Option ( a : t @ ype ) = [ b : bool ] option ( a , b )
# включить "share/atspre_staload.hats"fn show_value ( opt : Option int ): string = case + opt of | None () => "Нет значения" | Some ( s ) => tostring_int sреализовать main0 () : void = let val full = Some 42 и empty = None in println !( "show_value full → " , show_value full ); println !( "show_value empty → " , show_value empty ); конец
show_value полное → 42 show_value пустое → Нет значения
Начиная с 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
В F# тип параметра определяется как . [5]type 'a option = None | Some of 'a
let showValue = Option . fold ( fun _ x -> sprintf "Значение: %d" x ) "Значение отсутствует" пусть полный = Около 42 пусть пустой = Ни одного showValue полное |> printfn "showValue полное -> %s" showValue пустое |> printfn "showValue пустое -> %s"
showValue полное -> Значение: 42 showValue пустое -> Нет значения
В Haskell тип опции определяется как . [6]data Maybe a = Nothing | Just a
showValue :: Maybe Int -> String showValue = foldl ( \ _ x -> "Значение: " ++ show x ) "Значение отсутствует" main :: IO () main = do let full = Just 42 let empty = Nothing putStrLn $ "showValue полное -> " ++ showValue полное putStrLn $ "showValue пустое -> " ++ showValue пустое
showValue полное -> Значение: 42 showValue пустое -> Нет значения
В Idris тип опции определяется как .data Maybe a = Nothing | Just a
showValue : Может быть Int -> String
showValue = foldl (\ _ , x => "Значение равно " ++ show x ) "Значение отсутствует" main : IO ()
main = do let full = Just 42 let empty = Nothing putStrLn $ "showValue полное -> " ++ showValue полное putStrLn $ "showValue пустое -> " ++ showValue пустое
showValue полное -> Значение: 42 showValue пустое -> Нет значения
импорт стандарт / опции proc showValue ( opt : Option [ int ] ): string = opt . map ( proc ( x : int ): string = "Значение: " & $ x ). get ( "Нет значения" ) пусть полный = некоторый ( 42 ) пустой = нет ( int ) echo "showValue(полный) -> " , showValue ( полный ) echo "showValue(пустой) -> " , showValue ( пустой )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В OCaml тип опции определяется как . [7]type 'a option = None | Some of 'a
let show_value = Option . fold ~ none : "Значение отсутствует" ~ some :( fun x -> "Значение равно: " ^ string_of_int x )пусть () = пусть полный = Около 42 в пусть пустой = Ни одного в print_endline ( "show_value полное -> " ^ show_value полное ); print_endline ( "show_value пустое -> " ^ show_value пустое )
show_value полное -> Значение: 42 show_value пустое -> Нет значения
В Rust тип опции определяется как . [8]enum Option<T> { None, Some(T) }
fn show_value ( opt : Option <i32> ) -> String { opt.map_or ( "Нет значения" .to_owned ( ), | x | format ! ( "Значение: { } " , x ) ) } fn main () { пусть полный = Некоторый ( 42 ); пусть пустой = Нет ; println! ( "show_value(full) -> {}" , show_value ( full )); println! ( "show_value(empty) -> {}" , show_value ( empty )); }
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 ]): Unit = val full = Some ( 42 ) val empty = None println ( s"showValue(полный) -> ${ showValue ( полный ) } " ) println ( s"showValue ( пустой) -> ${ showValue ( пустой ) } " )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В стандартном ML тип опции определяется как .datatype 'a option = NONE | SOME of 'a
В Swift тип параметра определяется как , но обычно записывается как . [9]enum Optional<T> { case none, some(T) }
T?
func showValue ( _ opt : Int ?) -> String { return opt . map { "Значение: \( $0 ) " } ?? "Значение отсутствует" }пусть полный = 42 пусть пустой : Int ? = нольprint ( "showValue(полный) -> \( showValue ( полный )) " ) print ( "showValue(пустой) -> \( showValue ( пустой )) " )
showValue(full) -> Значение: 42 showValue(empty) -> Нет значения
В Zig добавьте ? перед именем типа, ?i32
чтобы сделать его необязательным.
Полезная нагрузка n может быть зафиксирована в операторе if или while , например , и предложение else оценивается, если оно равно .if (opt) |n| { ... } else { ... }
null
константа std = @import ( "std" ); fn showValue ( allocator : std.mem.Allocator , opt : ? i32 ) ! [] u8 { return if ( opt ) | n | std.fmt.allocPrint ( allocator , " Значение: { } " , . { n } ) else allocator.dupe ( u8 , " Значение отсутствует " ) ; } pub fn main () ! void { // Настраиваем распределитель и предупреждаем, если мы забудем освободить память. var gpa = std . heap . GeneralPurposeAllocator (.{}){}; defer std . debug . assert ( gpa . deinit () == . ok ); const allocator = gpa . allocator (); // Подготавливаем стандартный поток вывода. const stdout = std . io . getStdOut (). writer (); // Выполняем наш пример. const full = 42 ; const empty = null ; const full_msg = try showValue ( allocator , full ); отложить allocator . free ( full_msg ); try stdout . print ( "showValue(allocator, full) -> {s} \n " , .{ full_msg }); const empty_msg = try showValue ( allocator , empty ); отложить allocator.free ( empty_msg ); try stdout.print ( "showValue ( allocator, empty ) -> {s} \n " , . { empty_msg }) ; }
showValue(allocator, full) -> Значение: 42 showValue(allocator, empty) -> Нет значения