{{Short description|Encapsulation of an optional value in programming or type theory}} {{for|families of option contracts in finance|Option style}} {{multiple issues|section=| {{More citations needed|date=July 2019}} {{Original research|date=July 2019}} }}
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 <code>None</code> or <code>Nothing</code>), or which encapsulates the original data type <code>A</code> (often written <code>Just A</code> or <code>Some A</code>).
A distinct, but related concept outside of functional programming, which is popular in object-oriented programming, is called nullable types (often expressed as <code>A?</code>). The core difference between option types and nullable types is that option types support nesting (e.g. <code>Maybe (Maybe String)</code> ≠ <code>Maybe String</code>), while nullable types do not (e.g. <code>String??</code> = <code>String?</code>).
==Theoretical aspects== In type theory, it may be written as: <math>A^{?} = A + 1</math>. This expresses the fact that for a given set of values in <math>A</math>, an option type adds exactly one additional value (the empty value) to the set of valid values for <math>A</math>. 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.<ref>{{cite web|url=https://bartoszmilewski.com/2015/01/13/simple-algebraic-data-types/|title=Simple Algebraic Data Types|last=Milewski|first=Bartosz|date=2015-01-13|website=Bartosz Milewski's Programming Cafe|at=Sum types. "We could have encoded Maybe as: data Maybe a = Either () a"|language=en|archive-url=https://web.archive.org/web/20190818084741/https://bartoszmilewski.com/2015/01/13/simple-algebraic-data-types/|archive-date=2019-08-18|url-status=live|access-date=2019-08-18}}</ref> An option type is a particular case of a tagged union, where the <code>Nothing</code> is taken as (nullary constructor for a) singleton type. Tagged unions can generally be implemented by a combination of union types and record types using occurrence typing.<ref>https://arxiv.org/pdf/2111.03354 p. 8</ref>
The option type is also a monad where:<ref>{{cite web|url=http://www.learnyouahaskell.com/a-fistful-of-monads|title=A Fistful of Monads - Learn You a Haskell for Great Good!|website=www.learnyouahaskell.com|access-date=2019-08-18}}{{Dead link|date=August 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref>
<syntaxhighlight lang="haskell"> return = Just -- Wraps the value into a maybe
Nothing >>= f = Nothing -- Fails if the previous monad fails (Just x) >>= f = f x -- Succeeds when both monads succeed </syntaxhighlight>
The monadic nature of the option type is useful for efficiently tracking failure and errors.<ref>{{cite web|url=https://www.youtube.com/watch?v=t1e8gqXLbsU |archive-url=https://ghostarchive.org/varchive/youtube/20211220/t1e8gqXLbsU |archive-date=2021-12-20 |url-status=live|title=What is a Monad?|last=Hutton|first=Graham|date=Nov 25, 2017|website=Computerphile Youtube|access-date=Aug 18, 2019}}{{cbignore}}</ref>
== Examples == <!-- Gentle reminder to not add language examples that do not satisfy the laws. If you do not know what this means, please refrain from adding examples.
List of things that are NOT option types and therefore do not need to be added: - std::optional<T> in C++ - Nullable<T> (T?) in C# - Null (T?) in Dart - Optional<T> in Java - Nullable{T} in Julia - Nullable types (T?) in Kotlin - typing.Optional[T] (T | None) in Python - Definiteness (:D) in Raku -->
=== Ada === Ada does not implement option-types directly, however it provides discriminated types which can be used to parameterize a record. To implement a Option type, a Boolean type is used as the discriminant; the following example provides a generic to create an option type from any non-limited constrained type: <syntaxhighlight lang="ada"> generic -- Any constrained & non-limited type. type Element_Type is private; package Optional_Type is -- When the discriminant, Has_Element, is true there is an element field, -- when it is false, there are no fields (hence the null keyword). type Optional (Has_Element : Boolean) is record case Has_Element is when False => Null; when True => Element : Element_Type; end case; end record; end Optional_Type; </syntaxhighlight>
Example usage: <syntaxhighlight lang="ada"> package Optional_Integers is new Optional_Type (Element_Type => Integer); Foo : Optional_Integers.Optional := (Has_Element => True, Element => 5); Bar : Optional_Integers.Optional := (Has_Element => False); </syntaxhighlight>
=== Agda === {{Expand section|with=example usage|date=July 2022}} {{Further|Agda (programming language)}}
In Agda, the option type is named {{code|2=agda|Maybe}} with variants {{code|2=agda|nothing}} and {{code|2=agda|just a}}.
=== ATS === {{Further|ATS (programming language)}}
In ATS, the option type is defined as
<syntaxhighlight lang="ocaml"> datatype option_t0ype_bool_type (a: t@ype+, bool) = | Some(a, true) of a | None(a, false) stadef option = option_t0ype_bool_type typedef Option(a: t@ype) = [b:bool] option(a, b) </syntaxhighlight>
<syntaxhighlight lang="ocaml"> #include "share/atspre_staload.hats"
fn show_value (opt: Option int): string = case+ opt of | None() => "No value" | Some(s) => tostring_int s
implement main0 (): void = let val full = Some 42 and empty = None in println!("show_value full → ", show_value full); println!("show_value empty → ", show_value empty); end </syntaxhighlight>
<syntaxhighlight lang="output"> show_value full → 42 show_value empty → No value </syntaxhighlight>
=== C++ === Since C++17, the option type is defined in the standard library as {{code|2=C++|1=template <typename T> optional<T>}}.<ref name= "cppref.com_optional">{{Cite web |title=std::optional - cppreference.com |url=https://docs.cppreference.com/w/cpp/utility/optional.html |access-date=2026-01-06 |website=docs.cppreference.com}}</ref> <syntaxhighlight lang="cpp"> import std;
using std::nullopt; using std::optional;
constexpr optional<double> divide(double x, double y) noexcept { if (y != 0.0) { return x / y; }
return nullopt; }
void readDivisionResults(int x, int y) { optional<double> result = divide(x, y); if (result) { std::println("The quotient of x: {} and y: {} is {}.", x, y, result.value()); } else { std::println("The quotient of x: {} and y: {} is undefined!", x, y); } }
int main(int argc, char* argv[]) { readDivisionResults(1, 5); readDivisionResults(8, 0); } </syntaxhighlight>
In C++23, support for monadic operations for {{code|std::optional<T>}} is avaliable.<ref name="cppref.com_optional"/>
=== Elm === {{Expand section|with=example usage|date=July 2022}} {{Further|Elm (programming language)}}
In Elm, the option type is defined as {{code|2=elm|1=type Maybe a = Just a {{!}} Nothing}}.<ref>{{cite web |title=Maybe · An Introduction to Elm |url=https://guide.elm-lang.org/error_handling/maybe.html |website=guide.elm-lang.org}}</ref>
=== F# === {{Further|F Sharp (programming language)}}
In F#, the option type is defined as {{code|2=fsharp|1=type 'a option = None {{!}} Some of 'a}}.<ref>{{Cite web |title=Options |url=https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/options |access-date=2024-10-08 |website=fsharp.org}}</ref>
<syntaxhighlight lang="fsharp"> let showValue = Option.fold (fun _ x -> sprintf "The value is: %d" x) "No value"
let full = Some 42 let empty = None
showValue full |> printfn "showValue full -> %s" showValue empty |> printfn "showValue empty -> %s" </syntaxhighlight>
<syntaxhighlight lang="output"> showValue full -> The value is: 42 showValue empty -> No value </syntaxhighlight>
=== Haskell === {{Further|Haskell}}
In Haskell, the option type is defined as {{code|2=haskell|1=data Maybe a = Nothing {{!}} Just a}}.<ref>{{Cite web |title=6 Predefined Types and Classes |url=https://www.haskell.org/onlinereport/haskell2010/haskellch6.html#x13-1250006.1.8 |access-date=2022-06-15 |website=Haskell.org}}</ref>
<syntaxhighlight lang="haskell"> showValue :: Maybe Int -> String showValue = foldl (\_ x -> "The value is: " ++ show x) "No value"
main :: IO () main = do let full = Just 42 let empty = Nothing
putStrLn $ "showValue full -> " ++ showValue full putStrLn $ "showValue empty -> " ++ showValue empty </syntaxhighlight>
<syntaxhighlight lang="output"> showValue full -> The value is: 42 showValue empty -> No value </syntaxhighlight>
=== Idris === {{Further|Idris (programming language)}}
In Idris, the option type is defined as {{code|2=idris|1=data Maybe a = Nothing {{!}} Just a}}.
<syntaxhighlight lang="idris"> showValue : Maybe Int -> String showValue = foldl (\_, x => "The value is " ++ show x) "No value"
main : IO () main = do let full = Just 42 let empty = Nothing
putStrLn $ "showValue full -> " ++ showValue full putStrLn $ "showValue empty -> " ++ showValue empty </syntaxhighlight>
<syntaxhighlight lang="output"> showValue full -> The value is: 42 showValue empty -> No value </syntaxhighlight>
=== Java === {{Further|Java (programming language)}}
In Java, the option type is defined the standard library by the {{code|2=java|1=java.util.Optional<T>}} class.
<syntaxhighlight lang="java"> import java.util.Optional;
public class OptionExample { static String showValue(Optional<Integer> opt) { return opt.map(x -> String.format("The value is: %d", x)).orElse("No value"); }
public static void main(String[] args) { Optional<Integer> full = Optional.of(42); Optional<Integer> empty = Optional.empty();
System.out.printf("showValue(full): %s\n", showValue(full)); System.out.printf("showValue(empty): %s\n", showValue(empty)); } } </syntaxhighlight>
<syntaxhighlight lang="output"> showValue full -> The value is: 42 showValue empty -> No value </syntaxhighlight>
=== Nim === {{Expand section|with=the definition|date=July 2022}} {{Further|Nim (programming language)}}
<syntaxhighlight lang="nim"> import std/options
proc showValue(opt: Option[int]): string = opt.map(proc (x: int): string = "The value is: " & $x).get("No value")
let full = some(42) empty = none(int)
echo "showValue(full) -> ", showValue(full) echo "showValue(empty) -> ", showValue(empty) </syntaxhighlight>
<syntaxhighlight lang="output"> showValue(full) -> The Value is: 42 showValue(empty) -> No value </syntaxhighlight>
=== OCaml === {{Further|OCaml}}
In OCaml, the option type is defined as {{code|2=ocaml|1=type 'a option = None {{!}} Some of 'a}}.<ref>{{Cite web |title=OCaml library : Option |url=https://v2.ocaml.org/releases/4.13/api/Option.html#TYPEt |access-date=2022-06-15 |website=v2.ocaml.org}}</ref>
<syntaxhighlight lang="ocaml"> let show_value = Option.fold ~none:"No value" ~some:(fun x -> "The value is: " ^ string_of_int x)
let () = let full = Some 42 in let empty = None in
print_endline ("show_value full -> " ^ show_value full); print_endline ("show_value empty -> " ^ show_value empty) </syntaxhighlight>
<syntaxhighlight lang="output"> show_value full -> The value is: 42 show_value empty -> No value </syntaxhighlight>
=== Rocq === {{Expand section|with=example usage|date=July 2022}} {{Further|Rocq}}
In Rocq, the option type is defined as {{code|2=coq|1=Inductive option (A:Type) : Type := {{!}} Some : A -> option A {{!}} None : option A. }}.
=== Rust === {{Further|Rust (programming language)}}
In Rust, the option type is defined as {{code|2=rust|enum Option<T> { None, Some(T) } }}.<ref>{{cite web |url=https://doc.rust-lang.org/core/option/enum.Option.html |title=Option in core::option - Rust |date=2022-05-18 |access-date=2022-06-15 |website=doc.rust-lang.org}}</ref>
<syntaxhighlight lang="rust"> fn show_value(opt: Option<i32>) -> String { opt.map_or("No value".to_owned(), |x: i32| format!("The value is: {}", x)) }
fn main() { let full: Option<i32> = Some(42); let empty: Option<i32> = None;
println!("show_value(full) -> {}", show_value(full)); println!("show_value(empty) -> {}", show_value(empty)); } </syntaxhighlight>
<syntaxhighlight lang="output"> show_value(full) -> The value is: 42 show_value(empty) -> No value </syntaxhighlight>
=== Scala === {{Further|Scala (programming language)}}
In Scala, the option type is defined as {{code|2=scala|1=sealed abstract class Option[+A]}}, a type extended by {{code|2=scala|1=final case class Some[+A](value: A)}} and {{code|2=scala|1=case object None}}.
<syntaxhighlight lang="scala"> object Main: def showValue(opt: Option[Int]): String = opt.fold("No value")(x => s"The value is: $x")
def main(args: Array[String]): Unit = val full = Some(42) val empty = None
println(s"showValue(full) -> ${showValue(full)}") println(s"showValue(empty) -> ${showValue(empty)}")
</syntaxhighlight>
<syntaxhighlight lang="output"> showValue(full) -> The value is: 42 showValue(empty) -> No value </syntaxhighlight>
=== Standard ML === {{Expand section|with=example usage|date=July 2022}} {{Further|Standard ML}}
In Standard ML, the option type is defined as {{code|2=sml|1=datatype 'a option = NONE {{!}} SOME of 'a}}.
=== Swift === {{Further|Swift (programming language)}}
In Swift, the option type is defined as {{code|2=swift|enum Optional<T> { case none, some(T) } }} but is generally written as {{code|2=swift|T?}}.<ref>{{cite web|title=Apple Developer Documentation|url=https://developer.apple.com/documentation/swift/optional|access-date=2020-09-06|website=developer.apple.com}}</ref>
<syntaxhighlight lang="swift"> func showValue(_ opt: Int?) -> String { return opt.map { "The value is: \($0)" } ?? "No value" }
let full = 42 let empty: Int? = nil
print("showValue(full) -> \(showValue(full))") print("showValue(empty) -> \(showValue(empty))") </syntaxhighlight>
<syntaxhighlight lang="output"> showValue(full) -> The value is: 42 showValue(empty) -> No value </syntaxhighlight>
=== Zig === {{Further|Zig (programming language)}}
In Zig, add ? before the type name like <code>?i32</code> to make it an optional type.
Payload <var>n</var> can be captured in an ''if'' or ''while'' statement, such as {{code|2=zig|if (opt) {{!}}n{{!}} { ... } else { ... } }}, and an ''else'' clause is evaluated if it is <code>null</code>.
<syntaxhighlight lang="zig"> const std = @import("std");
fn showValue(gpa: std.mem.Allocator, opt: ?i32) ![]u8 { return if (opt) |n| std.fmt.allocPrint(gpa, "The value is: {}", .{n}) else gpa.dupe(u8, "No value"); }
pub fn main(init: std.process.Init) !void { // Prepare the standard output stream. var buffer: [1024]u8 = undefined; var writer = std.Io.File.stdout().writer(init.io, &buffer);
// Perform our example. const full = 42; const empty = null;
const full_msg = try showValue(init.gpa, full); defer init.gpa.free(full_msg); try writer.interface.print("showValue(init.gpa, full) -> {s}\n", .{full_msg});
const empty_msg = try showValue(init.gpa, empty); defer init.gpa.free(empty_msg); try writer.interface.print("showValue(init.gpa, empty) -> {s}\n", .{empty_msg});
try writer.interface.flush(); } </syntaxhighlight>
<syntaxhighlight lang="output"> showValue(init.gpa, full) -> The value is: 42 showValue(init.gpa, empty) -> No value </syntaxhighlight>
== See also == * Result type * Tagged union * Nullable type * Null object pattern * Exception handling * Pattern matching
== References == {{Reflist}}
{{Data types}}
Category:Data types Category:Type theory Category:Functional programming Category:Programming language comparisons <!-- Hidden categories below --> Category:Articles with example Ada code Category:Articles with example C++ code Category:Articles with example Haskell code Category:Articles with example Java code Category:Articles with example OCaml code Category:Articles with example Rust code Category:Articles with example Scala code Category:Articles with example Swift code