Chapter 18 Types
This chapter defines the syntax for types and describes the built-in types.
Types are divided into monotypes (ty) and polytypes(polyTy). The syntax for mono types are given below.
ty | ::= | tyvar | type variable names |
---|---|---|---|
{tyrow} | record types | ||
ty * * ty | tuple types () | ||
ty -> ty | function types | ||
tySeq longTycon | (parameterlized) datatypes | ||
(ty ) | |||
tyrow | ::= | lab : ty , tyrow | record field types |
tyvar are type variable names. As defined in Section 17.2, they are written as ’a,’foo or ’’a,’’foo. The latter form are for those equality type variables, which range only over types that admit equality. An type admits equality, called eqtype, is any type that does not contain function type constructor and built-in types that does not admit equality. A user defined datatype is an eqtype if it only contains eqtypes. For example, list defined below is an eqtype if is an eqtype.
datatype ’a list = nil | :: of ’a * ’a list
The function type constructor -> associates to the right so that int -> int -> int is interpreted as int -> (int -> int).
longTycon is a type constructor names defined by datatype declarations. Atomic types such as int are type constructors without type parameters (tySeq). SML#4.1.0 supports the following built-in atomic types and type constructors.
type constructor name | description | eqtype? |
int | 32 bit long signed integers | Yes |
int64 | 64 bit long signed integers | Yes |
int16 | 16 bit long signed integers | Yes |
int8 | 8 bit long signed integers | Yes |
intInf | unbounded signed integers | Yes |
word | 32 bit long unsigned integers | Yes |
word64 | 64 bit long unsigned integers | Yes |
word16 | 8 bit long unsigned integers | Yes |
word8 | 8 bit long unsigned integers | Yes |
real | floating point numbers) | No |
real32 | 32 floating point numbers | No |
char | characters | Yes |
string | strings | Yes |
exn | exceptions | No |
unit | unit values (()) | Yes |
ref | references (pointers) | Yes |
array | arrays | Yes |
vector | vectors | がeq型ならばYes |
The unit type is distinguished from the empty record type {} as a different type. This is the modification that is not backward-compatible to Standard ML.
The syntax for polytypes (polyTy) are given below.
polyTy | ::= | ty |
---|---|---|
[ boundtyvarList . ty ] | ||
ty -> polyTy | ||
polyTy * * polyTy | ||
{ polyTyrow } | ||
boundtyvarList | ::= | boundtyvar , boundtyvarList |
boundtyvar | ::= | tyvar kind |
kind | ::= | |
#{ tyrow } | ||
# kindName kind | ||
kindName | ::= | boxed unboxed reify eq |
polyTyrow | ::= | lab : polyTy , polyTyrow |
-
•
[ boundtyvarList . ty ] is the polymorphic type that makes the scope of bounded type variables boundtyvarList explicitly.
-
•
A bound type variable may have the following kind constraints kind. The record kind #{ tyrow } restricts the range of the bound type variable to record types that have at least fields indicated by tyrow. The boxed kind restricts it to the type of heap-allocated values. The unboxed kind is the complement of the boxed kind. The eq kind restricts it to eqtypes. The reify kind is just an annotation that the type reification feature is required and therefore does not restrict the range of the bound type variable.
The set of polytypes is the extension of the set of polytypes in the definition of Standard ML with record polymorphism, overloading and rank-1 polymorphism.
The following examples use a rank-1 polytype.
# fn x => (fn y => (x,y), nil);
val it = fn : [’a. ’a -> [’b. ’b -> ’a * ’b] * [’b. ’b list]]
In the interactive session, in addition to the above kinds, you may see the overload kind :: { tyList }, which restricts the range of the bound type variable to tyList. The current system restricts overloading to system defined primitives, and type variables with overload kind are not allowed in a user program.