Edge Rewrite
Jump to content

// Workers AI · dad joke modeWhat did the option type say? "I'm a call to action.

From Wikipedia, the free encyclopedia
(Redirected from Maybe type)

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

[edit]

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] 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.[2]

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

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.[4]

Examples

[edit]


Ada

[edit]

Ada does not implement option-types directly, however it provides discriminated types which can be used to parameterize a record. To implement an 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

[edit]

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

ATS

[edit]

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++

[edit]

Since C++17, the option type is defined in the standard library as template <typename T> optional<T>.[5]

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);
}


In C++23, support for monadic operations for std::optional<T> is available.[5]

Elm

[edit]

In Elm, the option type is defined as type Maybe a = Just a | Nothing.[6]

F#

[edit]

In F#, the option type is defined as type 'a option = None | Some of 'a.[7]

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

[edit]

In Haskell, the option type is defined as data Maybe a = Nothing | Just a.[8]

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

[edit]

In Idris, the option type is defined as 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

[edit]

In Java, the option type is defined the standard library by the java.util.Optional<T> class.

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));
    }
}
showValue full -> The value is: 42
showValue empty -> No value

Nim

[edit]
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

[edit]

In OCaml, the option type is defined as type 'a option = None | Some of 'a.[9]

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

Rocq

[edit]

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

Rust

[edit]

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

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));
}
show_value(full) -> The value is: 42
show_value(empty) -> No value

Scala

[edit]

In Scala, the option type is defined as sealed abstract class Option[+A], a type extended by final case class Some[+A](value: A) and 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

[edit]

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

Swift

[edit]

In Swift, the option type is defined as enum Optional<T> { case none, some(T) } but is generally written as T?.[11]

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

[edit]

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.

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

See also

[edit]

References

[edit]
  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. ↑ https://arxiv.org/pdf/2111.03354 p. 8
  3. ↑ "A Fistful of Monads - Learn You a Haskell for Great Good!". www.learnyouahaskell.com. Retrieved 2019-08-18.[permanent dead link]
  4. ↑ Hutton, Graham (Nov 25, 2017). "What is a Monad?". Computerphile Youtube. Archived from the original on 2021-12-20. Retrieved Aug 18, 2019.
  5. 1 2 "std::optional - cppreference.com". docs.cppreference.com. Retrieved 2026-01-06.
  6. ↑ "Maybe · An Introduction to Elm". guide.elm-lang.org.
  7. ↑ "Options". fsharp.org. Retrieved 2024-10-08.
  8. ↑ "6 Predefined Types and Classes". Haskell.org. Retrieved 2022-06-15.
  9. ↑ "OCaml library : Option". v2.ocaml.org. Retrieved 2022-06-15.
  10. ↑ "Option in core::option - Rust". doc.rust-lang.org. 2022-05-18. Retrieved 2022-06-15.
  11. ↑ "Apple Developer Documentation". developer.apple.com. Retrieved 2020-09-06.