6.4 | Type expressions

`typexpr` | ::= | `'` `ident`
| | | `_`
| | | `(` `typexpr` `)`
| | | [[`?`]`ident``:`] `typexpr` `->` `typexpr`
| | | `typexpr` { `*` `typexpr` }+
| | | `typeconstr`
| | | `typexpr` `typeconstr`
| | | `(` `typexpr` { `,` `typexpr` } `)` `typeconstr`
| | | `typexpr` `as` `'` `ident`
| | | `[` `variant-type` `]`
| | | `<` [`..`] `>`
| | | `<` `method-type` { `;` `method-type` } [`;` `..`] `>`
| | | `#` `class-path`
| | | `typexpr` `#` `class-path`
| | | `(` `typexpr` { `,` `typexpr` } ) `#` `class-path`
| | | `#` `typeconstr-path` [ `tag-list` ]
| | | `typexpr` `#` `typeconstr-path` [ `tag-list` ]
| | | `(` `typexpr` { `,` `typexpr` } ) `#` `typeconstr-path` [ `tag-list` ]
`method-type` | ::= | `method-name` `:` `typexpr`
`tag-list` | ::= | `[>` {````tag-name`}+ `]`

The table below shows the relative precedences and associativity of operators and non-closed type constructions. The constructions with higher precedences come first.

Operator | Associativity
Type constructor application | --
`*` | --
`->` | right
`as` | --

Type expressions denote types in definitions of data types as well as in type constraints over patterns and expressions.

Type variables

The type expression `'` `ident` stands for the type variable named `ident`. The type expression `_` stands for an anonymous type variable. In data type definitions, type variables are names for the data type parameters. In type constraints, they represent unspecified types that can be instantiated by any type to satisfy the type constraint.

Parenthesized types

The type expression `(` `typexpr` `)` denotes the same type as `typexpr`.

Function types

The type expression `typexpr`1 `->` `typexpr`2 denotes the type of functions mapping arguments of type `typexpr`1 to results of type `typexpr`2.
`label` `typexpr`1 `->` `typexpr`2 denotes the same function type, but the argument is labeled `label`.
`?``label` `typexpr`1 `->` `typexpr`2 denotes the type of functions mapping an optional labeled argument of type `typexpr`1 to results of type `typexpr`2. That is, the physical type of the function will be `typexpr`1 `option` `->` `typexpr`2.

Tuple types

The type expression `typexpr`1 `*` ... `*` `typexpr`n denotes the type of tuples whose elements belong to types `typexpr`1, ... `typexpr`n respectively.

Constructed types

Type constructors with no parameter, as in `typeconstr`, are type expressions.
The type expression `typexpr` `typeconstr`, where `typeconstr` is a type constructor with one parameter, denotes the application of the unary type constructor `typeconstr` to the type `typexpr`.
The type expression (`typexpr`1,..., `typexpr`n) `typeconstr`, where `typeconstr` is a type constructor with n parameters, denotes the application of the n-ary type constructor `typeconstr` to the types `typexpr`1 through `typexpr`n.

Recursive types

The type expression `typexpr` `as` `'` `ident` denotes the same type as `typexpr`, and also binds the type variable `ident` to type `typexpr` both in `typexpr` and in the remaining part of the type. If the type variable `ident` actually occurs in `typexpr`, a recursive type is created. Recursive types for which there exists a recursive path that does not contain an object type constructor are rejected.

Variant types

`variant-type` | ::= | [ `tag-spec` ] { `|` `tag-spec` }
| | | `>` [ `tag-spec` ] { `|` `tag-spec` }
| | | `<` [ `|` ] `tag-spec-full` { `|` `tag-spec-full` } [ `>` { ````tag-name` }+ ]
`tag-spec` | ::= | ````tag-name` [ `of` `typexpr` ]
`tag-spec-full` | ::= | ````tag-name` [ `of` `typexpr` ] { `&` `typexpr` }

Variant types describe the values a polymorphic variant may take.
The first case is an exact variant type: all possible tags are known, with their associated types, and they can all be present. Its structure is fully known. A special case is the empty type, with no tag, which contains no value.
The second case is an open variant type, describing a polymorphic variant value: it gives the list of all tags the value could take, with their associated types. This type is still compatible with a variant type containing more tags. A special case is the unknown type, which does not define any tag, and is compatible with any variant type.
The third case is a closed variant type. It gives information about all the possible tags and their associated types, and which tags are known to potentially appear in values. The above exact variant type is just an abbreviation for a closed variant type where all possible tags are also potentially present.
Full specification of variant tags are only used for non-exact closed types. They can be understood as a conjunctive type for the argument: it is intended to have all the types enumerated in the specification.
Such conjunctive constraints may be unsatisfiable. In such a case the corresponding tag may not be used in a value of this type. This does not mean that the whole type is not valid: one can still use other available tags.

Object types

An object type `<` `method-type` { `;` `method-type` } `>` is a record of method types.
The type `<` `method-type` { `;` `method-type` } `;` `..` `>` is the type of an object with methods and their associated types are described by `method-type`1, ..., `method-type`n, and possibly some other methods represented by the ellipsis. This ellipsis actually is a special kind of type variable (also called row variable in the literature) that stands for any number of extra method types.

#-types

The type `#` `class-path` is a special kind of abbreviation. This abbreviation unifies with the type of any object belonging to a subclass of class `class-path`. It is handled in a special way as it usually hides a type variable (an ellipsis, representing the methods that may be added in a subclass). In particular, it vanishes when the ellipsis gets instantiated. Each type expression `#` `class-path` defines a new type variable, so type `#` `class-path` `->` `#` `class-path` is usually not the same as type `#` `class-path` `as` `'` `ident` `->` `'` `ident`.
#-types can also be used to abbreviate variant types. Similarly they express the presence of a row variable, allowing further refinement of the type. Precisely, if `t` has been defined as the type `[` ``tag`1 `a`1 `|` ... `|`tag`n `a`n`]` then `#t` is the type `[<` ``tag`1 `a`1 `|` ...`|`tag`n `a`n`]`, and `#t[>` ``tag`1 ...``tag`k`]` is the type `[<` ``tag`1 `a`1 `|` ...`|`tag`n `a`n `>` ``tag`1 ...``tag`k`]`.

Variant and record types

There are no type expressions describing (defined) variant types nor record types, since those are always named, i.e. defined before use and referred to by name. Type definitions are described in section 6.8.1.