6.4 Type expressions
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 typexpr1 -> typexpr2 denotes the type of
functions mapping arguments of type typexpr1 to results of type
typexpr2.
label typexpr1 -> typexpr2 denotes the same function type, but
the argument is labeled label.
?label typexpr1 -> typexpr2 denotes the type of functions
mapping an optional labeled argument of type typexpr1 to results of
type typexpr2. That is, the physical type of the function will be
typexpr1 option -> typexpr2.
Tuple types
The type expression typexpr1 * ... * typexprn
denotes the type of tuples whose elements belong to types typexpr1,
... typexprn 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 (typexpr1,..., typexprn) typeconstr, where
typeconstr is a type constructor with n parameters, denotes the
application of the n-ary type constructor typeconstr to the types
typexpr1 through typexprn.
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 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.
The second case describes 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.
The third case is the type with no information: nothing is known about
which tags the variant is allowed to use. It only says that this must
be a variant.
The fourth case is the most general one. It gives information about
all the possible tags and their associated types, whether more tags
are allowed or not (with the ellipsis '..'), and which tags are known
to potentially appear in values.
Full specification of variant tags are only used in this last
form. They can be understood as a conjunctive type for the argument:
it is intended to have all the types enumerated in the
specification. If the first ampersand & appears just after the tag
name, or no type at all is given, then no argument is allowed.
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-type1, ..., method-typen, 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
[ `tag1 t1 | ... |`tagn tn] then \#t is the type
[< `tag1 t1 | ...|`tagn tn], and
#t[> `tag1 ...`tagk] is the type
[< `tag1 t1 | ...|`tagn tn > `tag1 ...`tagk].
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.