Unit

The unit type — spelled ! — has a single value, also !.

def Unit: ! = !

Unit is frequently used as an end-marker for other types. All composite types — such as pairs, eithers, and choices — have an obligatory “and then” part. The unit type does the job for the case of “and then nothing”.

For example, the pre-defined List<a> type has this definition:

type List<a> = recursive either {
  .end!,
  .item(a) self,
}

Each variant in an either type has an obligatory payload. For the node marking the end of the list, the payload is empty, and so it’s !.

Construction

The expression ! has type ! and is the only possible value for this type.

def Unit = !  // infers `Unit` to be of type `!`

Destruction

Being a data type, variables of type ! can be left unused.

If ! is a part of a larger type, it may be needed to assign it as a part of a pattern. For this purpose, the pattern ! will destruct a ! value without assigning it to a variable.

def TestUnitDestruction = do {
  let unit = !
  let ! = unit
} in !

This is useful when matching an end of a list:

dec GetFirstOrZero : [List<Int>] Int
def GetFirstOrZero = [list] list.case {
  .end!      => 0,  // `!` is a pattern here
  .item(x) _ => x,
}

Or when destructing a !-ended tuple:

dec SumPair : [(Int, Int)!] Int
def SumPair = [pair]
  let (x, y)! = pair  // `!` is a pattern here
  in Int.Add(x, y)

def Five =
  let pair = (2, 3)!
  in SumPair(pair)