Skip to main content

Unions, Tags & Pattern Matching

This page covers tagged union types and the match expression in TypR.

Defining tagged unions

type Shape <- .Circle(num) | .Square(num);
let s <- .Circle(3.14);
let n <- .None; # tag without payload

Each variant is prefixed with a dot (.) to distinguish it from regular type names.


The match expression

match s {
.Circle(r) => r * 2.0,
.Square(side) => side,
}

Available patterns

PatternExampleDescription
Tag with binding.Some(a) => adestructures and binds the payload
Tag without binding.None => 0matches a zero-payload tag
Type patternx as int => x + 1type cast/refinement
Record pattern:{nom: n, age: a} => adestructures a record
Tuple pattern:{a, b} => adestructures a tuple
Wildcard_ => defaultmatches anything
Variablev => vbinds and returns

Qualified union constructors

type Color <- .Red | .Blue;
Color.Red # qualified reference to a tag (bare, no :{...})

type Rgb <- list { r: int, g: int, b: int };
type Palette <- .Red | .Blue | Rgb;
Palette.Rgb:{ r = 10, g = 20, b = 30 } # Rgb is a record alias used as a union member

Important: Union.Variant:{ field = val } syntax only works when Variant is a record alias used directly as a union member — never for a real tag .Variant(...). To construct a tag, use .Variant(value), and .Variant(:{ ... }) when the payload is itself a record.


Generic tagged unions

Tagged unions work with generics for reusable patterns:

type Option`<T>` <- .Some(T) | .None;

let val: Option<int> <- .Some(42);
let empty: Option<int> <- .None;

match val {
.Some(n) => n,
.None => 0,
}