Read chapter 6.
New types can be created from combinations of existing types. Example:
> type imaginary = (real * real);
type imaginary = real * real
Any structure of type real * real is also of type imaginary.
Read section 6.1.3 in Ullman, Parametrized Type Definitions (not covered here).
This is where the real power of ML comes in. We can define types containing almost any sort of symbol or expression. Example:
> datatype fruit = Apple | Pear | Grape;
datatype fruit = Apple | Pear | Grape
These types are unlike types defined with the keyword type. These types are each unique. Each symbol in the list is a constructor.
> Apple;
val it = Apple : fruit
Any of the constructors can be used wherever an object of type fruit is required.
> fun isApple(x) = (x = Apple);
val isApple = fn : fruit -> bool
This function is a function from fruit to bool.
> isApple( Apple );
val it = true : bool
Data constructors can take arguments.
> datatype number = Int of int | Real of real | Imag of imag;
datatype number = Imag of real * real | Int of int | Real of real
> Int 4;
val it = Int 4 : number
> Imag (0.707, 1.414);
val it = Imag (0.707, 1.414) : number