SML# Document Version 4.0.0
III Reference manual

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
 | ty1 *  * tyn tuple types (n2)
 | 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.0.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.