A user-defined data type is introduced with the
typekeyword and a modifier
structural.The modifier indicates if the type is unique by its name, or if it is unique only by its structure. (SeeTypesfor an informal description of Unison's type system.)
=sign splits the definition into aleft-hand sideand aright-hand side,much like term definitions.
The left-hand side is the data type being defined. It gives a name for the data type and declares a newtype constructorwith that name (here it's named
Optional),followed by names for any type arguments (here there is one and it’s called
a).These names are bound as type variables in the right-hand side. The right-hand side may also refer to the name given to the type in the left-hand side, in which case it is a recursive type declaration. Note that the fully saturated type construction
Optional Natis a type, whereas
Optionalby itself is a type constructor, not a type (it requires a type argument in order to construct a type).
The right-hand side consists of zero or more data constructors separated by
|.These aredata constructorsfor the type, or ways in which values of the type can be constructed. Each case declares a name for a data constructor (here the data constructors are
Some),followed by thetypesof the arguments to the constructor.
When Unison compiles a type definition, it generates a term for each data constructor. Here they are the terms
Some : a -> Optional a,and
None : Optional a.It also generatespatternsfor matching on data (seePattern Matching).
Note that these terms and patterns receive qualified names: if the type named
x.y.Zhas a data constructor
C,the generated term and pattern for
Cwill be named
The general form of a type declaration is as follows:
<unique|structural<[<regular-identifier>]?>?> type TypeConstructor p1 p2 … pn = DataConstructor_1 | DataConstructor_2 .. | DataConstructor_n