Option type

Last updated

In programming languages (especially functional programming languages) and type theory, an option type or maybe type is a polymorphic type that represents encapsulation of an optional value; e.g., it is used as the return type of functions which may or may not return a meaningful value when they are applied. It consists of a constructor which either is empty (often named None or Nothing), or which encapsulates the original data type A (often written Just A or Some A).

Contents

A distinct, but related concept outside of functional programming, which is popular in object-oriented programming, is called nullable types (often expressed as A?). The core difference between option types and nullable types is that option types support nesting (e.g. Maybe (Maybe String)Maybe String), while nullable types do not (e.g. String?? = String?).

Theoretical aspects

In type theory, it may be written as: . This expresses the fact that for a given set of values in , an option type adds exactly one additional value (the empty value) to the set of valid values for . This is reflected in programming by the fact that in languages having tagged unions, option types can be expressed as the tagged union of the encapsulated type plus a unit type. [1]

In the Curry–Howard correspondence, option types are related to the annihilation law for ∨: x∨1=1.[ how? ]

An option type can also be seen as a collection containing either one or zero elements.[ original research? ]

The option type is also a monad where: [2]

return=Just-- Wraps the value into a maybeNothing>>=f=Nothing-- Fails if the previous monad fails(Justx)>>=f=fx-- Succeeds when both monads succeed

The monadic nature of the option type is useful for efficiently tracking failure and errors. [3]

Examples

Agda

In Agda, the option type is named Maybe with variants nothing and justa.

C++

Since C++17, the option type is defined in the standard library as template<typenameT>std::optional<T>.

Coq

In Coq, the option type is defined as Inductiveoption(A:Type):Type:=|Some:A->optionA|None:optionA..

Elm

In Elm, the option type is defined as typeMaybea=Justa|Nothing. [4]

F#

letshowValue=Option.fold(fun_x->sprintf"The value is: %d"x)"No value"letfull=Some42letempty=NoneshowValuefull|>printfn"showValue full -> %s"showValueempty|>printfn"showValue empty -> %s"
showValue full -> The value is: 42showValue empty -> No value

Haskell

In Haskell, the option type is defined as dataMaybea=Nothing|Justa. [5]

showValue::MaybeInt->StringshowValue=foldl(\_x->"The value is: "++showx)"No value"main::IO()main=doletfull=Just42letempty=NothingputStrLn$"showValue full -> "++showValuefullputStrLn$"showValue empty -> "++showValueempty
showValue full -> The value is: 42showValue empty -> No value

Idris

In Idris, the option type is defined as dataMaybea=Nothing|Justa.

showValue:MaybeInt->String showValue=foldl(\_,x=>"The value is "++showx)"No value"main:IO() main=doletfull=Just42letempty=NothingputStrLn$"showValue full -> "++showValuefull putStrLn$"showValue empty -> "++showValueempty 
showValue full -> The value is: 42showValue empty -> No value

Nim

importstd/optionsprocshowValue(opt:Option[int]):string=opt.map(proc(x:int):string="The value is: "&$x).get("No value")letfull=some(42)empty=none(int)echo"showValue(full) -> ",showValue(full)echo"showValue(empty) -> ",showValue(empty)
showValue(full) -> The Value is: 42showValue(empty) -> No value

OCaml

In OCaml, the option type is defined as type'aoption=None|Someof'a. [6]

letshow_value=Option.fold~none:"No value"~some:(funx->"The value is: "^string_of_intx)let()=letfull=Some42inletempty=Noneinprint_endline("show_value full -> "^show_valuefull);print_endline("show_value empty -> "^show_valueempty)
show_value full -> The value is: 42show_value empty -> No value

Rust

In Rust, the option type is defined as enumOption<T>{None,Some(T)}. [7]

fnshow_value(opt: Option<i32>)-> String{opt.map_or("No value".to_owned(),|x|format!("The value is: {}",x))}fnmain(){letfull=Some(42);letempty=None;println!("show_value(full) -> {}",show_value(full));println!("show_value(empty) -> {}",show_value(empty));}
show_value(full) -> The value is: 42show_value(empty) -> No value

Scala

In Scala, the option type is defined as sealedabstractclassOption[+A], a type extended by finalcaseclassSome[+A](value:A) and caseobjectNone.

objectMain:defshowValue(opt:Option[Int]):String=opt.fold("No value")(x=>s"The value is: $x")defmain(args:Array[String]):Unit=valfull=Some(42)valempty=Noneprintln(s"showValue(full) -> ${showValue(full)}")println(s"showValue(empty) -> ${showValue(empty)}")
showValue(full) -> The value is: 42showValue(empty) -> No value

Standard ML

In Standard ML, the option type is defined as datatype'aoption=NONE|SOMEof'a.

Swift

In Swift, the option type is defined as enumOptional<T>{casenone,some(T)} but is generally written as T?. [8]

funcshowValue(_opt:Int?)->String{returnopt.map{"The value is: \($0)"}??"No value"}letfull=42letempty:Int?=nilprint("showValue(full) -> \(showValue(full))")print("showValue(empty) -> \(showValue(empty))")
showValue(full) -> The value is: 42showValue(empty) -> No value

Zig

In Zig, add ? before the type name like ?i32 to make it an optional type.

Payload n can be captured in an if or while statement, such as if(opt)|n|{...}else{...}, and an else clause is evaluated if it is null.

conststd=@import("std");fnshowValue(allocator:std.mem.Allocator,opt:?i32)![]u8{returnif(opt)|n|std.fmt.allocPrint(allocator,"The value is: {}",.{n})elseallocator.dupe(u8,"No value");}pubfnmain()!void{// Set up an allocator, and warn if we forget to free any memory.vargpa=std.heap.GeneralPurposeAllocator(.{}){};deferstd.debug.assert(gpa.deinit()==.ok);constallocator=gpa.allocator();// Prepare the standard output stream.conststdout=std.io.getStdOut().writer();// Perform our example.constfull=42;constempty=null;constfull_msg=tryshowValue(allocator,full);deferallocator.free(full_msg);trystdout.print("showValue(allocator, full) -> {s}\n",.{full_msg});constempty_msg=tryshowValue(allocator,empty);deferallocator.free(empty_msg);trystdout.print("showValue(allocator, empty) -> {s}\n",.{empty_msg});}
showValue(allocator, full) -> The value is: 42 showValue(allocator, empty) -> No value

See also

Related Research Articles

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

In object-oriented (OO) and functional programming, an immutable object is an object whose state cannot be modified after it is created. This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change, but the object's state appears unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.

In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following:

In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type or coproduct, is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time, and a tag field explicitly indicates which one is in use. It can be thought of as a type that has several "cases", each of which should be handled correctly when that type is manipulated. This is critical in defining recursive datatypes, in which some component of a value may have the same type as that value, for example in defining a type for representing trees, where it is necessary to distinguish multi-node subtrees and leaves. Like ordinary unions, tagged unions can save storage by overlapping storage areas for each type, since only one is in use at a time.

In functional programming, a monad is a structure that combines program fragments (functions) and wraps their return values in a type with additional computation. In addition to defining a wrapping monadic type, monads define two operators: one to wrap a value in the monad type, and another to compose together functions that output values of the monad type. General-purpose languages use monads to reduce boilerplate code needed for common operations. Functional languages use monads to turn complicated sequences of functions into succinct pipelines that abstract away control flow, and side-effects.

<span class="mw-page-title-main">Foreach loop</span> Control flow statement for traversing items in a collection

In computer programming, foreach loop is a control flow statement for traversing items in a collection. foreach is usually used in place of a standard for loop statement. Unlike other for loop constructs, however, foreach loops usually maintain no explicit counter: they essentially say "do this to everything in this set", rather than "do this x times". This avoids potential off-by-one errors and makes code simpler to read. In object-oriented languages, an iterator, even if implicit, is often used as the means of traversal.

In class-based, object-oriented programming, a constructor is a special type of function called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.

typedef is a reserved keyword in the programming languages C, C++, and Objective-C. It is used to create an additional name (alias) for another data type, but does not create a new type, except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type. As such, it is often used to simplify the syntax of declaring complex data structures consisting of struct and union types, although it is also commonly used to provide specific descriptive type names for integer data types of varying sizes.

A class in C++ is a user-defined type or data structure declared with keyword class that has data and functions as its members whose access is governed by the three access specifiers private, protected or public. By default access to members of a C++ class is private. The private members are not accessible outside the class; they can be accessed only through methods of the class. The public members form an interface to the class and are accessible outside the class.

In computer programming, a semipredicate problem occurs when a subroutine intended to return a useful value can fail, but the signalling of failure uses an otherwise valid return value. The problem is that the caller of the subroutine cannot tell what the result means in this case.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".

The null coalescing operator is a binary operator that is part of the syntax for a basic conditional expression in several programming languages, including C#, PowerShell as of version 7.0.0, Perl as of version 5.10, Swift, and PHP 7.0.0. While its behavior differs between implementations, the null coalescing operator generally returns the result of its left-most operand if it exists and is not null, and otherwise returns the right-most operand. This behavior allows a default value to be defined for cases where a more specific value is not available.

This Comparison of programming languages (associative arrays) compares the features of associative array data structures or array-lookup processing for over 40 computer programming languages.

In computer programming, variadic templates are templates that take a variable number of arguments.

<span class="mw-page-title-main">Rust (programming language)</span> General-purpose programming language

Rust is a multi-paradigm, general-purpose programming language that emphasizes performance, type safety, and concurrency. It enforces memory safety, meaning that all references point to valid memory, without requiring the use of automated memory management techniques, such as garbage collection. To simultaneously enforce memory safety and prevent data races, its "borrow checker" tracks the object lifetime of all references in a program during compilation. Rust was influenced by ideas from functional programming, including immutability, higher-order functions, and algebraic data types. It is popular for systems programming.

In object-oriented programming, the safe navigation operator is a binary operator that returns null if its first argument is null; otherwise it performs a dereferencing operation as specified by the second argument.

<span class="mw-page-title-main">Zig (programming language)</span> A general-purpose programming language, and toolchain to build Zig/C/C++ code

Zig is an imperative, general-purpose, statically typed, compiled system programming language designed by Andrew Kelley. It is intended to be a successor to the C programming language, with the goals of being even smaller and simpler to program in while also offering modern features, new optimizations and a variety of safety mechanisms while not as demanding of runtime safety as seen in other languages. It is distinct from languages like Go, Rust and Carbon, which have similar goals but also target the C++ space.

References

  1. Milewski, Bartosz (2015-01-13). "Simple Algebraic Data Types". Bartosz Milewski's Programming Cafe. Sum types. "We could have encoded Maybe as: data Maybe a = Either () a". Archived from the original on 2019-08-18. Retrieved 2019-08-18.
  2. "A Fistful of Monads - Learn You a Haskell for Great Good!". www.learnyouahaskell.com. Retrieved 2019-08-18.
  3. Hutton, Graham (Nov 25, 2017). "What is a Monad?". Computerphile Youtube. Archived from the original on 2021-12-20. Retrieved Aug 18, 2019.
  4. "Maybe · An Introduction to Elm". guide.elm-lang.org.
  5. "6 Predefined Types and Classes". www.haskell.org. Retrieved 2022-06-15.
  6. "OCaml library : Option". v2.ocaml.org. Retrieved 2022-06-15.
  7. "Option in core::option - Rust". doc.rust-lang.org. 2022-05-18. Retrieved 2022-06-15.
  8. "Apple Developer Documentation". developer.apple.com. Retrieved 2020-09-06.