Datatypes and basic patterns
A datatype introduces a nominal type with a closed set of constructors. Use it when a value may have one of several meaningful shapes.
Declare constructors
Section titled “Declare constructors”Constructors may have no payload, positional payloads, or named payloads:
datatype Message Quit Text(String) Move{x: Int, y: Int}endThere is no punctuation between constructors. Construct values with an
explicit Type::Constructor path:
datatype Message Quit Text(String) Move{x: Int, y: Int}end
func initial_message() -> Message do Message::Move{x: 0, y: 0}endConstructor names need to be unique only inside their own datatype.
Match with switch
Section titled “Match with switch”A switch evaluates its target once and considers cases from top to bottom:
datatype Message Quit Text(String) Move{x: Int, y: Int}end
func describe(message : Message) -> String do switch message case Message::Quit then "quit" case Message::Text(text) then text case Message::Move{x, y} then "move " ++ x.to_string() ++ "," ++ y.to_string() endendThe checker requires the cases to be exhaustive. Every case body must produce
one common result type. Bindings such as text, x, and y exist only in
their own case body.
Wildcards and binders
Section titled “Wildcards and binders”_ matches any value without creating a binding. A lower name matches any
value and binds it:
datatype Status Ready Waiting(Int) Failed(String)end
func is_ready(status : Status) -> Bool do switch status case Status::Ready then true case _ then false endendUse a wildcard only when all ignored cases are intentionally equivalent. A fully enumerated switch is more robust when different alternatives should remain visible.
Single-constructor datatypes
Section titled “Single-constructor datatypes”A single-constructor datatype is useful when a value needs nominal identity:
datatype UserId UserId(Int)end
func raw_id(id : UserId) -> Int do id._0endDirect payload field access is available because the static type determines
the only possible constructor. Named payloads use their declared field names.
For a multi-constructor datatype, inspect the value with switch instead.
Generic datatypes, guards, nested patterns, aliases, and or-patterns are covered in Advanced pattern matching and Generic programming.
Next: error handling.