option type
{{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 None
or Nothing
), or which encapsulates the original data type A
(often written Just A
or Some A
).
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
{{multiple issues|section=yes|{{Importance section|section|date=July 2019}}
{{Original research|section|date=August 2019}}}}
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.{{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}}
In the Curry–Howard correspondence, option types are related to the annihilation law for ∨: x∨1=1.{{How|date=August 2019|title=It is unclear how this is the case, and there are no links to external references that explain this.}}
An option type can also be seen as a collection containing either one or zero elements.{{Original research inline|date=July 2019}}
The option type is also a monad where:{{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}}
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
The monadic nature of the option type is useful for efficiently tracking failure and errors.{{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}}
Examples
= 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:
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;
Example usage:
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);
= 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
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)
- 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
show_value full → 42
show_value empty → No value
= C++ =
Since C++17, the option type is defined in the standard library as {{code|2=C++|1=template
std::optional
if(y != 0.0)
return x / y;
return {};
}
= Coq =
{{Expand section|with=example usage|date=July 2022}}
{{Further|Coq (software)}}
In Coq, the option type is defined as {{code|2=coq|1=Inductive option (A:Type) : Type := {{!}} Some : A -> option A {{!}} None : option A. }}.
= 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}}.{{cite web |title=Maybe · An Introduction to Elm |url=https://guide.elm-lang.org/error_handling/maybe.html |website=guide.elm-lang.org}}
= 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}}.{{Cite web |title=Options |url=https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/options |access-date=2024-10-08 |website=fsharp.org}}
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"
showValue full -> The value is: 42
showValue empty -> No value
= Haskell =
{{Further|Haskell (programming language)}}
In Haskell, the option type is defined as {{code|2=haskell|1=data Maybe a = Nothing {{!}} Just a}}.{{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=www.haskell.org}}
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
showValue full -> The value is: 42
showValue empty -> No value
= Idris =
{{Further|Idris (programming language)}}
In Idris, the option type is defined as {{code|2=idris|1=data Maybe a = Nothing {{!}} Just a}}.
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
showValue full -> The value is: 42
showValue empty -> No value
= Java =
{{Further|Java (programming language)}}
In Java, the option type is defined the standard library by the {{code|2=java|1=java.util.Optional
import java.util.Optional;
class Option {
static String showValue(Optional
return opt.map(x -> String.format("The value is: %d", x)).orElse("No value");
}
public static void main(String[] args) {
Optional
Optional
System.out.printf("showValue(full) -> %s\n", showValue(full));
System.out.printf("showValue(empty) -> %s\n", showValue(empty));
}
}
showValue full -> The value is: 42
showValue empty -> No value
= Nim =
{{Expand section|with=the definition|date=July 2022}}
{{Further|Nim (programming language)}}
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)
showValue(full) -> The Value is: 42
showValue(empty) -> No value
= OCaml =
{{Further|OCaml}}
In OCaml, the option type is defined as {{code|2=ocaml|1=type 'a option = None {{!}} Some of 'a}}.{{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}}
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)
show_value full -> The value is: 42
show_value empty -> No value
= Rust =
{{Further|Rust (programming language)}}
In Rust, the option type is defined as {{code|2=rust|enum Option
fn show_value(opt: Option
opt.map_or("No value".to_owned(), |x| format!("The value is: {}", x))
}
fn main() {
let full = Some(42);
let empty = None;
println!("show_value(full) -> {}", show_value(full));
println!("show_value(empty) -> {}", show_value(empty));
}
show_value(full) -> The value is: 42
show_value(empty) -> No value
= 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}}.
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)}")
showValue(full) -> The value is: 42
showValue(empty) -> No value
= 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
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))")
showValue(full) -> The value is: 42
showValue(empty) -> No value
= Zig =
{{Further|Zig (programming language)}}
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 {{code|2=zig|if (opt) {{!}}n{{!}} { ... } else { ... } }}, and an else clause is evaluated if it is null
.
const std = @import("std");
fn showValue(allocator: std.mem.Allocator, opt: ?i32) ![]u8 {
return if (opt) |n|
std.fmt.allocPrint(allocator, "The value is: {}", .{n})
else
allocator.dupe(u8, "No value");
}
pub fn main() !void {
// Set up an allocator, and warn if we forget to free any memory.
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
// Prepare the standard output stream.
const stdout = std.io.getStdOut().writer();
// Perform our example.
const full = 42;
const empty = null;
const full_msg = try showValue(allocator, full);
defer allocator.free(full_msg);
try stdout.print("showValue(allocator, full) -> {s}\n", .{full_msg});
const empty_msg = try showValue(allocator, empty);
defer allocator.free(empty_msg);
try stdout.print("showValue(allocator, empty) -> {s}\n", .{empty_msg});
}
showValue(allocator, full) -> The value is: 42
showValue(allocator, empty) -> No value
See also
References
{{Reflist}}
{{Data types}}
Category:Articles with example C++ code
Category:Articles with example Haskell 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