Unions are for representing values that can be in one of a fixed number of states: a switch can be on or off; a street light can be red, yellow, or green; a box can hold something or be empty, etc.

For C programmers: they are like enums and tagged unions. For OCaml/Haskell programmers: they are sum types.

Defining Unions

Unions are defined with the union declaration:

union IntBox: Free is
    case Empty;
    case Full is
        value: Int32;

Unions have a set of cases, each case has a unique name and a (potentially empty) set of fields like a record. Here, the type IntBox represents values that can either be Empty (in which case it holds no data) or Full (in which case it holds a value of type Int32).

Constructing Unions

Unions are constructed using a function call-like syntax, like records, except you use the name of the particular case:

let box1: IntBox := Empty();
let box2: IntBox := Full(value => 32);

The Case Statement

Unlike records, the contents of a union can’t be accessed using dot notation. You need the case statement:

let box: IntBox := ...;
case box of
    when Empty do
        -- Do something with an empty box.
        printLn("Box is empty");
    when Full(value: Int32) do
        -- Do something with the value of a full box.
        print("Box has value: ");
end case;

If box is Empty, this code will print:

Box is empty

If box was constructed like Full(value => 123), then the above code will print:

Box has value: 123

When a case has no values, the corresponding when clause takes no bindings:

when Empty do

When a case has values, the corresponding when clause needs one binding for each field in the case:

when Full(value: Int32) do

You can rename bindings:

when Full(value as v: Int32) do