6.6. Sum type arguments
A record says "all of these"; a data type says "one of these". Unrolled, a
data argument becomes a set of options that exclude one another, one per
constructor. An argument-free constructor is a bare flag. A constructor with
fields takes exactly as many values as it has fields, in order.
--' A shape to measure
data Shape
--' a circle of some radius
= Circle Real
--' a box, width then height
| Rect Real Real
--' a point, with no size
| Dot
--' Measure a shape
area ::
--' the shape
--' @unroll
Shape ->
Real
$ ./shapes area -h
...
Optional arguments:
--circle <Real> a circle of some radius
constructor of Shape
--rect <Real> <Real> a box, width then height
constructor of Shape
--dot a point, with no size
constructor of Shape
...
$ ./shapes area --rect 2.0 3.5
7
$ ./shapes area --dot
0
$ ./shapes area --dot --circle 1.0
error: the argument '--dot' cannot be used with '--circle <Real>'
Each option is the constructor’s name in lowercase, and its help is the
constructor’s docstring. A value inside an arm is read the way an argument of
its type would be, so a field of a data type takes a bare constructor
(--solid red) and a field of a record type takes JSON or a file path.
Exactly one arm is required, unless the argument may be omitted — a ?Shape
with no arm given is null — or it declares a default, which may be a bare
constructor:
--' Count the corners, defaulting to a dot
count ::
--' the shape
--' @unroll
--' @default dot
Shape ->
Int
To a program the argument is still one value. --json-help lists it under the
role alternatives with its arms, and the MCP tool exposes a single property
holding the constructor’s JSON, since a model has no need for the flags.
@unroll on a data argument does not combine with @arg, @many or
@stdin: the constructors are the options, and there is nothing else to name.