Option type
≈ 8 min read
Names in other languages
No names in other languages are held for this entry yet.
Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.
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? ).
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== In type theory, it may be written as: A^{?} = A + 1 . This expresses the fact that for a given set of values in A , an option type adds exactly one additional value (the empty value) to the set of valid values for A . 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. An option type is a particular case of a tagged union, where the Nothing 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. The option type is also a monad where: 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. 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); 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 import std; using std::nullopt; using std::optional; constexpr optional divide(double x, double y) noexcept { if (y != 0.0) { return x / y; } return nullopt; } void readDivisionResults(int x, int y) { optional 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); } In C++23, support for monadic operations for is available. 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 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 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 import java.util.Optional; public class OptionExample { static String showValue(Optional opt) { return opt.map(x -> String.format("The value is: %d", x)).orElse("No value"); } public static void main(String[] args) { Optional full = Optional.of(42); Optional empty = Optional.empty(); 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 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 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 fn show_value(opt: Option ) -> String { opt.map_or("No value".to_owned(), |x: i32| format!("The value is: {}", x)) } fn main() { let full: Option = Some(42); let empty: Option = 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 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 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 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(); } showValue(init.gpa, full) -> The value is: 42 showValue(init.gpa, empty) -> No value
Text derived from https://en.wikipedia.org/w/index.php?oldid=1363002104 under CC BY-SA 4.0; modifications have been made.