integer numbers floating-point numbers

+addition -subtraction and unary negation *multiplication /integer division modremainder of integer division

+.addition -.subtraction and unary negation *.multiplication /.division **exponentiation

#`1`

`;;`

`- : int = 1`

#`1`

`+`

`2`

`;;`

`- : int = 3`

#`9`

`/`

`2`

`;;`

`- : int = 4`

#`1`

`1`

mod

`3`

`;;`

`- : int = 2`

`(* limits of the representation *)`

`(* of integers *)`

#`2`

`1`

`4`

`7`

`4`

`8`

`3`

`6`

`5`

`0`

`;;`

`- : int = 2`

#`2`

`.`

`0`

`;;`

`- : float = 2`

#`1`

`.`

`1`

`+.`

`2`

`.`

`2`

`;;`

`- : float = 3.3`

#`9`

`.`

`1`

`/.`

`2`

`.`

`2`

`;;`

`- : float = 4.13636363636`

#`1`

`.`

`/.`

`0`

`.`

`;;`

`- : float = inf`

`(* limits of the representation *)`

`(* of floating-point numbers *)`

#`2`

`2`

`2`

`2`

`2`

`2`

`2`

`2`

`2`

`2`

`2`

`2`

`.`

`1`

`1`

`1`

`1`

`1`

`;;`

`- : float = 222222222222`

Figure 2.1: Operations on numbers.

#`2`

`=`

`2`

`.`

`0`

`;;`

`Characters 5-8:`

`This expression has type float but is here used with type int`

#`3`

`.`

`0`

`=`

`float_of_int`

`3`

`;;`

`- : bool = true`

In the same way, operations on floating-point numbers are distinct from those on integers.

#`3`

`+`

`2`

`;;`

`- : int = 5`

#`3`

`.`

`0`

`+.`

`2`

`.`

`0`

`;;`

`- : float = 5`

#`3`

`.`

`0`

`+`

`2`

`.`

`0`

`;;`

`Characters 0-3:`

`This expression has type float but is here used with type int`

# sin

`3`

`.`

`1`

`4`

`1`

`5`

`9`

`;;`

`- : float = 2.65358979335e-06`

An ill-defined computation, such as a division by zero, will raise an exception (see page ??) which interrupts the computation. Floating-point numbers have a representation for infinite values (printed as

functions on floats trigonometric functions

ceilfloorsqrtsquare root expexponential lognatural log log10log base 10

coscosine sinsine tantangent acosarccosine asinarcsine atanarctangent

# ceil

`3`

`.`

`4`

`;;`

`- : float = 4`

# floor

`3`

`.`

`4`

`;;`

`- : float = 3`

# ceil

(`-.`

`3`

`.`

`4`

)`;;`

`- : float = -3`

# floor

(`-.`

`3`

`.`

`4`

)`;;`

`- : float = -4`

# sin

`1`

`.`

`5`

`7`

`0`

`7`

`8`

`;;`

`- : float = 0.999999999867`

# sin

(asin

`0`

`.`

`7`

`0`

`7`

)`;;`

`- : float = 0.707`

# acos

`0`

`.`

`0`

`;;`

`- : float = 1.57079632679`

# asin

`3`

`.`

`1`

`4`

`;;`

`- : float = nan`

Figure 2.2: Functions on floats.

#`'B'`

`;;`

`- : char = 'B'`

# int_of_char

`'B'`

`;;`

`- : int = 66`

#`"is a string"`

`;;`

`- : string = "is a string"`

#(string_of_int

`1`

`9`

`8`

`7`

)

`^`

`" is the year Caml was created"`

`;;`

`- : string = "1987 is the year Caml was created"`

Even if a string contains the characters of a number, it won't be possible to use it in operations on numbers without carrying out an explicit conversion.

Numerous functions on character strings are gathered in the

#`"1999"`

`+`

`1`

`;;`

`Characters 1-7:`

`This expression has type string but is here used with type int`

#(int_of_string

`"1999"`

)

`+`

`1`

`;;`

`- : int = 2000`

notnegation &&sequential and ||sequential or

&synonym for &&orsynonym for ||

Figure 2.3: Operators on booleans.

The operators

#true`;;`

`- : bool = true`

# not

true`;;`

`- : bool = false`

#true

`&&`

false`;;`

`- : bool = false`

The equality and comparison operators are described in figure 2.4. They are polymorphic, i.e., they can be used to compare two integers as well as two character strings. The only constraint is that their two operands must be of the same type (see page ??).

=structural equality ==physical equality <>negation of =!=negation of ==

<less than >greater than <=less than or equal to >=greater than or equal to

Figure 2.4: Equality and comparison operators.

#`1`

`<=`

`1`

`1`

`8`

`&&`

(`1`

`=`

`2`

`||`

`not`

(`1`

`=`

`2`

))`;;`

`- : bool = true`

#`1`

`.`

`0`

`<=`

`1`

`1`

`8`

`.`

`0`

`&&`

(`1`

`.`

`0`

`=`

`2`

`.`

`0`

`||`

`not`

(`1`

`.`

`0`

`=`

`2`

`.`

`0`

))`;;`

`- : bool = true`

#`"one"`

`<`

`"two"`

`;;`

`- : bool = true`

#`0`

`<`

`'0'`

`;;`

`Characters 4-7:`

`This expression has type char but is here used with type int`

Structural equality tests the equality of two values by traversing their structure, whereas physical equality tests whether the two values occupy the same region in memory. These two equality operators return the same result for simple values: booleans, characters, integers and constant constructors (page ??).

Floating-point numbers and character strings are considered structured values.

This value will often be used in imperative programs (3, page ??) for functions which carry out side effects. Functions whose result is the value

# ()`;;`

`- : unit = ()`

When there is no ambiguity, it can be written more simply:

#(

`1`

`2`

`,`

`"October"`

)`;;`

`- : int * string = 12, "October"`

The functions

#`1`

`2`

`,`

`"October"`

`;;`

`- : int * string = 12, "October"`

These two functions accept pairs whose components are of any type whatsoever. They are polymorphic, in the same way as equality.

# fst

(

`1`

`2`

`,`

`"October"`

)`;;`

`- : int = 12`

# snd

(

`1`

`2`

`,`

`"October"`

)`;;`

`- : string = "October"`

The type

# fst;;`- : 'a * 'b -> 'a = <fun>`

# fst

(

`"October"`

`,`

`1`

`2`

)`;;`

`- : string = "October"`

#(

`6`

`5`

`,`

`'B'`

`,`

`"ascii"`

)`;;`

`- : int * char * string = 65, 'B', "ascii"`

The functions

There is indeed a difference between the type of a pair and that of a triplet. The type

# snd

(

`6`

`5`

`,`

`'B'`

`,`

`"ascii"`

)`;;`

`Characters 7-25:`

`This expression has type int * char * string but is here used with type`

`'a * 'b`

# []`;;`

`- : 'a list = []`

#`[`

`1`

`;`

`2`

`;`

`3`

`]`

`;;`

`- : int list = [1; 2; 3]`

#`[`

`1`

`;`

`"two"`

`;`

`3`

`]`

`;;`

`Characters 14-17:`

`This expression has type int list but is here used with type string list`

The function which adds an element at the head of a list is the infix operator :: . It is the analogue of Lisp's

#`1`

`::`

`2`

`::`

`3`

`::`

`[]`

`;;`

`- : int list = [1; 2; 3]`

Concatenation of two lists is also an infix operator

#`[`

`1`

`]`

`@`

`[`

`2`

`;`

`3`

`]`

`;;`

`- : int list = [1; 2; 3]`

#`[`

`1`

`;`

`2`

`]`

`@`

`[`

`3`

`]`

`;;`

`- : int list = [1; 2; 3]`

The other list manipulation functions are defined in the

In this last example, it is indeed problematic to request retrieval of the first element of an empty list. It is for this reason that the system raises an exception (see page ??).

# List.hd

`[`

`1`

`;`

`2`

`;`

`3`

`]`

`;;`

`- : int = 1`

# List.hd`[]`

`;;`

`Uncaught exception: Failure("hd")`

The expression

#if

`3`

`=`

`4`

then

`0`

else

`4`

`;;`

`- : int = 4`

#if

`3`

`=`

`4`

then

`"0"`

else

`"4"`

`;;`

`- : string = "4"`

#if

`3`

`=`

`4`

then

`0`

else

`"4"`

;;`Characters 20-23:`

`This expression has type string but is here used with type int`

A conditional construct is itself an expression and its evaluation returns a value.

#(if

`3`

`=`

`5`

then

`8`

else

`1`

`0`

)

`+`

`5`

`;;`

`- : int = 15`

The

` `

(). Consequently, the type of the expression
A global declaration defines the binding between the name

#let`yr`

`=`

`"1999"`

`;;`

`val yr : string = "1999"`

#let`x`

`=`

`int_of_string`

(yr)`;;`

`val x : int = 1999`

# x`;;`

`- : int = 1999`

# x

`+`

`1`

`;;`

`- : int = 2000`

#let`new_yr`

`=`

`string_of_int`

(x

`+`

`1`

)`;;`

`val new_yr : string = "2000"`

let name_{1} = expr_{1} |

and name_{2} = expr_{2} |

: |

and name_{n} = expr_{n} ;; |

A simultaneous declaration declares different symbols at the same level. They won't be known until the end of all the declarations.

#let`x`

`=`

`1`

and`y`

`=`

`2`

`;;`

`val x : int = 1`

`val y : int = 2`

# x

`+`

`y`

`;;`

`- : int = 3`

#let`z`

`=`

`3`

and`t`

`=`

`z`

`+`

`2`

`;;`

`Characters 18-19:`

`Unbound value z`

It is possible to gather several global declarations in the same phrase; then printing of their types and their values does not take place until the end of the phrase, marked by double ``

A global declaration can be masked by a new declaration of the same name (see page ??).

#let`x`

`=`

`2`

let`y`

`=`

`x`

`+`

`3`

`;;`

`val x : int = 2`

`val y : int = 5`

The name

The local declaration binding

#let`xl`

`=`

`3`

in`xl`

`*`

`xl`

`;;`

`- : int = 9`

` `

`*`

` `

xl.
A local declaration masks all previous declarations of the same name, but the previous value is reinstated upon leaving the scope of the local declaration:

# xl`;;`

`Characters 1-3:`

`Unbound value xl`

A local declaration is an expression and can thus be used to construct other expressions:

#let`x`

`=`

`2`

`;;`

`val x : int = 2`

#let`x`

`=`

`3`

in`x`

`*`

`x`

`;;`

`- : int = 9`

# x

`*`

`x`

`;;`

`- : int = 4`

#(let`x`

`=`

`3`

in`x`

`*`

`x`

)

`+`

`1`

`;;`

`- : int = 10`

Local declarations can also be simultaneous.

let |
name_{1} = expr_{1} |

and |
name_{2} = expr_{2} |

: | |

and |
name_{n} = expr_{n} |

in |
expr ;; |

#let`a`

`=`

`3`

`.`

`0`

and`b`

`=`

`4`

`.`

`0`

in`sqrt`

(a`*.`

a

`+.`

`b`

`*.`

b)`;;`

`- : float = 5`

# b`;;`

`Characters 0-1:`

`Unbound value b`

Thus the function which squares its argument is written:

The Objective CAML system deduces its type. The function type

#function`x`

`->`

`x`

`*`

x`;;`

`- : int -> int = <fun>`

Application of a function to an argument is written as the function followed by the argument.

The evaluation of an application amounts to evaluating the body of the function, here x

#(function`x`

`->`

`x`

`*`

`x`

)

`5`

`;;`

`- : int = 25`

` `

`*`

` `

x, where the
formal parameter, `5`

.In the construction of a function expression, expr is any expression whatsoever. In particular, expr may itself be a function expression.

#function`x`

`->`

(function`y`

`->`

`3`

`*`

x

`+`

`y`

)`;;`

`- : int -> int -> int = <fun>`

The parentheses are not required. One can write more simply:

The type of this expression can be read in the usual way as the type of a function which expects two integers and returns an integer value. But in the context of a functional language such as Objective CAML we are dealing more precisely with the type of a function which expects an integer and returns a function value of type

#function`x`

`->`

function`y`

`->`

`3`

`*`

x

`+`

`y`

`;;`

`- : int -> int -> int = <fun>`

#(function`x`

`->`

function`y`

`->`

`3`

`*`

x

`+`

`y`

)

`5`

`;;`

`- : int -> int = <fun>`

One can, of course, use the function expression in the usual way by applying it to two arguments. One writes:

When one writes f

#(function`x`

`->`

function`y`

`->`

`3`

`*`

x

`+`

`y`

)

`4`

`5`

`;;`

`- : int = 17`

` `

a` `

b, there is an implicit parenthesization on
the left which makes this expression equivalent to: ` `

a` `

b.Let's examine the application

` `

x` `

->` `

` `

y` `

->` `

`3`

`*`

x` `

`+`

` `

y` `

`4`

` `

`5`

` `

x` `

->` `

` `

y` `

->` `

`3`

`*`

x` `

`+`

` `

y` `

`4`

` `

y` `

->` `

`3`

`*`

`4`

` `

`+`

` `

y
`4`

in `3`

`*`

x` `

`+`

` `

y.
Applying this value (which is a function) to `5`

we get the
final value `3`

`*`

`4`

`+`

`5`

= `1`

`7`

:

#(function`x`

`->`

function`y`

`->`

`3`

`*`

x

`+`

`y`

)

`4`

`5`

`;;`

`- : int = 17`

But, as its type indicates, this last expression expects not two, but only one argument: a pair of integers. Trying to pass two arguments to a function which expects a pair or trying to pass a pair to a function which expects two arguments results in a type error:

#function

(x`,`

y)`->`

`3`

`*`

x

`+`

`y`

`;;`

`- : int * int -> int = <fun>`

#(function

(x`,`

y)`->`

`3`

`*`

x

`+`

`y`

)

`4`

`5`

`;;`

`Characters 29-30:`

`This expression has type int but is here used with type int * int`

#(function`x`

`->`

function`y`

`->`

`3`

`*`

x

`+`

`y`

)

(`4`

`,`

`5`

)`;;`

`Characters 39-43:`

`This expression has type int * int but is here used with type int`

It allows one to omit repetitions of the

This form is still encountered often, in particular in the libraries provided with the Objective CAML distribution.

#fun`x`

`y`

`->`

`3`

`*`

x

`+`

`y`

`;;`

`- : int -> int -> int = <fun>`

#(fun`x`

`y`

`->`

`3`

`*`

x

`+`

`y`

)

`4`

`5`

`;;`

`- : int = 17`

#let`m`

`=`

`3`

`;;`

`val m : int = 3`

#function`x`

`->`

`x`

`+`

`m`

`;;`

`- : int -> int = <fun>`

#(function`x`

`->`

`x`

`+`

`m`

)

`5`

`;;`

`- : int = 8`

When application of a closure to an argument returns a new closure, the latter possesses within its environment all the bindings necessary for a future application. The subsection on the scope of variables (see page ??) details this notion. We will return to the memory representation of a closure in chapter 4 (page ??) as well as chapter 12 (page ??).

The function expressions used until now are

#let`succ`

`=`

function`x`

`->`

`x`

`+`

`1`

`;;`

`val succ : int -> int = <fun>`

# succ

`4`

`2`

`0`

`;;`

`- : int = 421`

#let`g`

`=`

function`x`

`->`

function`y`

`->`

`2`

`*`

x

`+`

`3`

`*`

y`;;`

`val g : int -> int -> int = <fun>`

# g

`1`

`2`

;;`- : int = 8`

To simplify writing, the following notation is allowed:

which is equivalent to the following form:

The following declarations of

#let`succ`

`x`

`=`

`x`

`+`

`1`

`;;`

`val succ : int -> int = <fun>`

#let`g`

`x`

`y`

`=`

`2`

`*`

x

`+`

`3`

`*`

y`;;`

`val g : int -> int -> int = <fun>`

The completely functional character of Objective CAML is brought out by the following example, in which the function

#let`h1`

`=`

`g`

`1`

`;;`

`val h1 : int -> int = <fun>`

# h1

`2`

`;;`

`- : int = 8`

One can also, starting from g, define a function h2 by fixing the value of the second parameter, y, of g:

#let`h2`

`=`

function`x`

`->`

`g`

`x`

`2`

`;;`

`val h2 : int -> int = <fun>`

# h2

`1`

`;;`

`- : int = 8`

`3`

` `

`+`

` `

`5`

for the
application of `3`

and `5`

. To use the
symbol (

The following example defines the function

` `

`+`

` `

#(

`+`

)`;;`

`- : int -> int -> int = <fun>`

#let`succ`

`=`

(

`+`

)

`1`

`;;`

`val succ : int -> int = <fun>`

# succ

`3`

`;;`

`- : int = 4`

It is also possible to define new operators. We define an operator

#let

(

`++`

)`c1`

`c2`

`=`

(fst`c1`

)`+`

(fst`c2`

)`,`

(snd`c1`

)`+`

(snd`c2`

)`;;`

`val ++ : int * int -> int * int -> int * int = <fun>`

#let`c`

`=`

(`2`

`,`

`3`

)`;;`

`val c : int * int = 2, 3`

# c

`++`

`c`

`;;`

`- : int * int = 4, 6`

There is an important limitation on the possible operators. They must contain only

`@`

, etc. ) and
not letters or digits. Certain functions predefined as infixes are
exceptions to the rule. They are listed as follows:

#let`h`

`=`

function`f`

`->`

function`y`

`->`

(f`y`

)

`+`

`y`

`;;`

`val h : (int -> int) -> int -> int = <fun>`

Application is implicitly parenthesized to the left, but function types are implicitly parenthesized to the right. Thus the type of the function

Higher order functions offer elegant possibilities for dealing with lists. For example the function

# List.map`;;`

`- : ('a -> 'b) -> 'a list -> 'b list = <fun>`

#let`square`

`x`

`=`

`string_of_int`

(x`*`

x)`;;`

`val square : int -> string = <fun>`

# List.map`square`

`[`

`1`

;

`2`

;

`3`

;

`4`

`]`

`;;`

`- : string list = ["1"; "4"; "9"; "16"]`

As another example, the function

# List.for_all`;;`

`- : ('a -> bool) -> 'a list -> bool = <fun>`

# List.for_all

(function`n`

`->`

`n`

`<>`

`0`

)

`[-`

`3`

;

`-`

`2`

;

`-`

`1`

;

`1`

;

`2`

;

`3`

`]`

`;;`

`- : bool = true`

# List.for_all

(function`n`

`->`

`n`

`<>`

`0`

)

`[-`

`3`

;

`-`

`2`

;

`0`

;

`1`

;

`2`

;

`3`

`]`

`;;`

`- : bool = false`

` `

p` `

`=`

` `

e. But
since

#let`p`

`=`

`p`

`^`

`"-suffix"`

`;;`

`Characters 9-10:`

`Unbound value p`

#let`p`

`=`

`"prefix"`

`;;`

`val p : string = "prefix"`

#let`p`

`=`

`p`

`^`

`"-suffix"`

`;;`

`val p : string = "prefix-suffix"`

In Objective CAML, variables are statically bound. The environment used to execute the application of a closure is the one in effect at the moment of its declaration (static scope) and not the one in effect at the moment of application (dynamic scope).

The function

#let`p`

`=`

`1`

`0`

`;;`

`val p : int = 10`

#let`k`

`x`

`=`

(x`,`

`p`

`,`

`x`

`+`

p)`;;`

`val k : int -> int * int * int = <fun>`

# k`p`

`;;`

`- : int * int * int = 10, 10, 20`

#let`p`

`=`

`1`

`0`

`0`

`0`

`;;`

`val p : int = 1000`

# k`p`

`;;`

`- : int * int * int = 1000, 10, 1010`

`1`

`0`

in the environment of the closure We can equally well use the syntactic facility for defining function values while indicating the function parameters:

By way of example, here is the function

`0`

and the
value of its argument, inclusive.
It may be noted that this function does not terminate if its argument is strictly negative.

#let

rec`sigma`

`x`

`=`

if`x`

`=`

`0`

then

`0`

else`x`

`+`

`sigma`

(x`-`

`1`

)`;;`

`val sigma : int -> int = <fun>`

# sigma

`1`

`0`

`;;`

`- : int = 55`

A recursive value is in general a function. The compiler rejects some recursive declarations whose values are not functions:

We will see however that in certain cases such declarations are allowed (see page ??).

#let

rec`x`

`=`

`x`

`+`

`1`

`;;`

`Characters 13-18:`

`This kind of expression is not allowed as right-hand side of `let rec'`

The

#let

rec`even`

`n`

`=`

(n`<>`

`1`

)

`&&`

((n`=`

`0`

)

or

(odd

(n`-`

`1`

)))

and

`odd`

`n`

`=`

(n`<>`

`0`

)

`&&`

((n`=`

`1`

)

or

(even

(n`-`

`1`

)))

`;;`

`val even : int -> bool = <fun>`

`val odd : int -> bool = <fun>`

# even

`4`

`;;`

`- : bool = true`

# odd

`5`

`;;`

`- : bool = true`

In the same way, local declarations can be recursive. This new definition of

#let`sigma`

`x`

`=`

let

rec`sigma_rec`

`x`

`=`

if`x`

`=`

`0`

then

`0`

else`x`

`+`

`sigma_rec`

(x`-`

`1`

)

in

if

(x`<`

`0`

)

then

`"error: negative argument"`

else

`"sigma = "`

`^`

(string_of_int

(sigma_rec`x`

))`;;`

`val sigma : int -> string = <fun>`

The need to give a return value of the same type, whether the argument is negative or not, has forced us to give the result in the form of a character string. Indeed, what value should be returned by

#let`make_pair`

`a`

`b`

`=`

(a`,`

b)`;;`

`val make_pair : 'a -> 'b -> 'a * 'b = <fun>`

#let`p`

`=`

`make_pair`

`"paper"`

`4`

`5`

`1`

`;;`

`val p : string * int = "paper", 451`

#let`a`

`=`

`make_pair`

`'B'`

`6`

`5`

`;;`

`val a : char * int = 'B', 65`

# fst`p`

`;;`

`- : string = "paper"`

# fst`a`

`;;`

`- : char = 'B'`

Functions are called polymorphic if their return value or one of their parameters is of a type which need not be specified. The type synthesizer contained in the Objective CAML compiler finds the most general type for each expression. In this case, Objective CAML uses variables, here

With Objective CAML's polymorphic functions, we get the advantages of being able to write generic code usable for values of every type, while still preserving the execution safety of static typing. Indeed, although

` `

`'B'`

` `

`6`

`5`

` `

`"paper"`

` `

`4`

`5`

`1`

The

So it can be applied to the function

#let`app`

`=`

function`f`

`->`

function`x`

`->`

`f`

`x`

`;;`

`val app : ('a -> 'b) -> 'a -> 'b = <fun>`

# app`odd`

`2`

;;`- : bool = false`

The identity function (

#let`id`

`x`

`=`

`x`

`;;`

`val id : 'a -> 'a = <fun>`

# app`id`

`1`

`;;`

`- : int = 1`

The

It can be seen that the result of

#let`compose`

`f`

`g`

`x`

`=`

`f`

(g`x`

)`;;`

`val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>`

#let`add1`

`x`

`=`

`x`

`+`

`1`

and`mul5`

`x`

`=`

`x`

`*`

`5`

in`compose`

`mul5`

`add1`

`9`

`;;`

`- : int = 50`

Values other than functions can be polymorphic as well. For example, this is the case for the empty list:

#let`l`

`=`

`[]`

`;;`

`val l : 'a list = []`

The following example demonstrates that type synthesis indeed arises from resolution of the constraints coming from function application and not from the value obtained upon execution.

The type of

#let`t`

`=`

`List.tl`

`[`

`2`

`]`

`;;`

`val t : int list = []`

Objective CAML generates parameterized types for every function which doesn't use the form of its arguments. This polymorphism is called parametric polymorphism

The syntactic form of a type constraint is as follows:

When it runs into such a constraint, the type synthesizer will take it into account while constructing the type of the expression. Using type constraints lets one:

- make the type of the parameters of a function visible;
- forbid the use of a function outside its intended context;
- specify the type of an expression, which will be particularly useful for mutable values (see page ??).

#let`add`

(x`:`

int)

(y`:`

int)

`=`

`x`

`+`

`y`

`;;`

`val add : int -> int -> int = <fun>`

#let`make_pair_int`

(x`:`

int)

(y`:`

int)

`=`

`x`

`,`

y;;`val make_pair_int : int -> int -> int * int = <fun>`

#let`compose_fn_int`

(f

`:`

`int`

`->`

`int`

)

(g

`:`

`int`

`->`

`int`

)

(x`:`

int)

`=`

`compose`

`f`

`g`

`x;;`

`val compose_fn_int : (int -> int) -> (int -> int) -> int -> int = <fun>`

#let`nil`

`=`

([]

`:`

`string`

`list`

);;`val nil : string list = []`

#`'H'`

::nil;;`Characters 5-8:`

`This expression has type string list but is here used with type char list`

Restricting polymorphism this way lets us control the type of an expression better by constraining the polymorphism of the type deduced by the system. Any defined type whatsoever may be used, including ones containing type variables, as the following example shows:

The symbol

#let`llnil`

`=`

([]

`:`

'a`list`

`list`

)`;;`

`val llnil : 'a list list = []`

#`[`

`1`

;`2`

;`3`

`]::`

`llnil`

`;;`

`- : int list list = [[1; 2; 3]]`

Here we are dealing with constraints, and not replacing Objective CAML's type synthesis with explicit typing. In particular, one cannot generalize types beyond what inference permits.

#let`add_general`

(x`:`

'a)

(y`:`

'b)

`=`

`add`

`x`

`y`

`;;`

`val add_general : int -> int -> int = <fun>`

Type constraints will be used in module interfaces (14) as well as in class declarations (15).

Here, the test for the terminal case of recursive functions is implemented by a conditional. Hence a programming style closer to Lisp. We will see how to give a more ML character to these definitions when we present another way of defining functions by case (see page ??).

Next, we define the function

#let`null`

`l`

`=`

(l

`=`

`[]`

)`;;`

`val null : 'a list -> bool = <fun>`

The function

#let

rec`size`

`l`

`=`

if`null`

`l`

then

`0`

else

`1`

`+`

(size

(List.tl`l`

))`;;`

`val size : 'a list -> int = <fun>`

# size`[]`

`;;`

`- : int = 0`

# size

`[`

`1`

;`2`

;`1`

`8`

;`2`

`2`

`]`

`;;`

`- : int = 4`

` `

n` `

f computes the value The

#let

rec`iterate`

`n`

`f`

`=`

if`n`

`=`

`0`

then

(function`x`

`->`

`x`

)

else`compose`

`f`

(iterate

(n`-`

`1`

)`f`

)`;;`

`val iterate : int -> ('a -> 'a) -> 'a -> 'a = <fun>`

Using

The

#let

rec`power`

`i`

`n`

`=`

let`i_times`

`=`

(

`*`

)`i`

in

`iterate`

`n`

`i_times`

`1`

`;;`

`val power : int -> int -> int = <fun>`

# power

`2`

`8`

`;;`

`- : int = 256`

First we define the function

` `

x` `

f_list
returns the list of results of applying each element of
f_list to x.

#let

rec`apply_fun_list`

`x`

`f_list`

`=`

if`null`

`f_list`

then`[]`

else

((List.hd`f_list`

)`x`

)::(apply_fun_list`x`

(List.tl`f_list`

))`;;`

`val apply_fun_list : 'a -> ('a -> 'b) list -> 'b list = <fun>`

# apply_fun_list

`1`

`[`

(

`+`

)

`1`

;(

`+`

)

`2`

;(

`+`

)

`3`

`]`

`;;`

`- : int list = [2; 3; 4]`

The function mk_mult_fun_list returns the list of functions multiplying their argument by i, for i varying from

`0`

to n.

#let`mk_mult_fun_list`

`n`

`=`

let

rec`mmfl_aux`

`p`

`=`

if`p`

`=`

`n`

then

`[`

(

`*`

)`n`

`]`

else

((

`*`

)`p`

)`::`

(mmfl_aux

(p`+`

`1`

))

in

(mmfl_aux

`1`

)`;;`

`val mk_mult_fun_list : int -> (int -> int) list = <fun>`

We obtain the multiplication table of 7 by:

#let`multab`

`n`

`=`

`apply_fun_list`

`n`

(mk_mult_fun_list

`1`

`0`

)`;;`

`val multab : int -> int list = <fun>`

# multab

`7`

`;;`

`- : int list = [7; 14; 21; 28; 35; 42; 49; 56; 63; 70]`

` `

f` `

a` `

`[`

e1;` `

e2;` `

`...`

` `

;` `

en`]`

returns f` `

`...`

` `

` `

` `

a` `

e1` `

e2` `

`...`

` `

en. So there are

#let

rec`fold_left`

`f`

`a`

`l`

`=`

if`null`

`l`

then`a`

else`fold_left`

`f`

(`f`

`a`

(List.hd`l`

))

(List.tl`l`

)`;;`

`val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>`

The function

#let`sum_list`

`=`

`fold_left`

(`+`

)

`0`

`;;`

`val sum_list : int list -> int = <fun>`

# sum_list

`[`

`2`

;`4`

;`7`

`]`

`;;`

`- : int = 13`

Or else, the concatenation of the elements of a list of strings:

#let`concat_list`

`=`

`fold_left`

(`^`

)

`""`

`;;`

`val concat_list : string list -> string = <fun>`

# concat_list

`[`

`"Hello "`

;

`"world"`

`;`

`"!"`

`]`

`;;`

`- : string = "Hello world!"`