20 CHAPTER 3. FURTHER CAML
(* ------------------------------------------------------ *)
(* This function tests if (x,y,z) is a Pythagorean triple *)
(* ------------------------------------------------------ *)
let pythag x y z =
x * x + y * y = z * z;;
(*comments*) pythag (*can*) 3 (*go*) 4 (*almost*) 5 (*anywhere*)
(* and (* can (* be (* nested *) quite *) arbitrarily *) *);;
3.1 Basic datatypes and operations
CAML features several built-in primitive types. From these, composite types may
be built using various type constructors. For the moment, we will only use the
function space constructor -> and the Cartesian product constructor *, but we will
see in due course which others are provided, and how to define new types and type
constructors. The primitive types that concern us now are:
• The type unit. This is a 1-element type, whose only element is written ().
Obviously, something of type unit conveys no information, so it is commonly
used as the return type of imperatively written ‘functions’ that perform a
side-effect, such as include above. It is also a convenient argument where
the only use of a function type is to delay evaluation.
• The type bool. This is a 2-element type of booleans (truth-values) whose
elements are written true and false.
• The type int. This contains some finite subset of the positive and negative
integers. Typically the permitted range is from −2
30
(−1073741824) up to
2
30
− 1 (1073741823).
1
The numerals are written in the usual way, optionally
with a negation sign, e.g. 0, 32, -25.
• The type string contains strings (i.e. finite sequences) of characters. They
are written and printed between double quotes, e.g. "hello". In order to
encode include special characters in strings, C-like escape sequences are used.
For example, \" is the double quote itself, and \n is the newline character.
The above values like (), false, 7 and "caml" are all to be regarded as fixed
constants. There are other constants corresponding to operations on the basic types.
Some of these may be written as infix operators, for the sake of familiarity. These
have a notion of precedence so that expressions are grouped together as one would
expect. For example, we write x + y rather than + x y and x < 2 * y + z rather
than < x (+ (* 2 y) z). The logical operator not also has a special parsing
status, in that the usual left-associativity rule is reversed for it: not not p means
not (not p). User-defined functions may be granted infix status via the #infix
directive. For example, here is a definition of a function performing composition of
functions:
1
We will see later how to use an alternative type of integers with unlimited precision.