Optionality via variants
ral has no Option type and no null. Optionality — a value that may be present
or absent — is expressed as an open variant, idiomatically `some v and
`none, passed as an ordinary value and discriminated by case. Every
Option a record carries is this variant (Datum for Option<T>), so an absent
principal, error, target or note is `none, never the empty string.
This follows from two other commitments:
- Arguments are not where optionality lives, because every invocable has fixed arity: the caller always supplies every argument, and the value it supplies carries the presence or absence.
- Absence is data, not a sentinel: a null that inhabits every type reintroduces exactly the silent collapse the value/command separation removes.
A variant makes the two cases distinct in the type and forces the consumer to handle both.
Record fields give a second route to the same end, but only so far: scoped labels and the update rule express defaults at the level of data when the records being merged are known where the merge is written. Over a record whose fields are not known there — a row-polymorphic parameter — no merge can supply a default, because a row slot is a label and a type and nothing else: there is no slot that may be missing, and no term asks whether a field is there. A field that may or may not be there is therefore a variant, like any other absence.
This is a hard rule: do not add an Option/Maybe builtin or a null literal;
reach for an open variant.