``` OCaml
# let rec split = function
| [] -> ([], [])
| h :: t ->
    let ss, gs = split t in
    match h with
    | `Sheep _ as s -> (s :: ss, gs)
    | `Goat _ as g -> (ss, g :: gs);
val split :
    [< `Goat of 'a | `Sheep of 'b ] list ->
    [> `Sheep of 'b ] list * [> `Goat of 'a ] list = <fun>
```

## Polymorphic variant abbreviation patterns

If the type `[( 'a , 'b ,...)] typeconstr = [ ` tag-name₁ typexpr₁ | ... | ` tag-nameₙ typexprₙ ]` is defined, then the pattern `# typeconstr` is a shorthand for the following or-pattern: `(` tag-name₁ (`_` : typexpr₁ ) | ... | ` tag-nameₙ (`_` : typexprₙ )`)`. It matches all values of type ` [< typeconstr ]`.

``` OCaml
# type 'a rectangle = [ `Square of 'a | `Rectangle of 'a * 'a]
    type 'a shape = [ `Circle of 'a | 'a rectangle]

let tryRectangle = function
| #rectangle as r -> Some r
| `Circle _ -> None;;

type 'a rectangle = [ `Rectangle of 'a * 'a | `Square of 'a ]
type 'a shape = [ `Circle of 'a | `Rectangle of 'a * 'a | `Square of 'a ]
val tryRectangle :
    [< `Circle of 'a | `Rectangle of 'b * 'b | `Square of 'b ] ->
    [> `Rectangle of 'b * 'b | `Square of 'b ] option = <fun>
```

## Tuple patterns

The pattern `pattern₁ , ..., patternₙ` matches `n`-tuples whose components match the patterns `pattern₁` through `patternₙ`. That is, the pattern matches the tuple values `(v₁, ..., vₙ)` such that `patternᵢ` matches `vᵢ` for `i = 1, ..., n`.

``` OCaml
# let vector (x0, y0) (x1, y1) =
    (x1 - . x0, y1 - . y0);;
val vector : float * float -> float * float -> float * float = <fun>
```

## Record patterns

The pattern `{ field₁ [= pattern₁] ; ... ; fieldₙ [= patternₙ] }` matches records that define at least the fields `field₁` through `fieldₙ`, and such that the value associated to `fieldᵢ` matches the pattern `patternᵢ`, for `i = 1, ..., n`. A single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, and a single qualified identifier `module-path` . `fieldₖ` stands for `module-path` . `fieldₖ = fieldₖ`. The record value can define more fields than `field₁ ... fieldₙ`; the values associated to these extra fields are not taken into account for
```h
# let is_empty = function
| [] -> true
| _ :: _ -> false;;
val is_empty : 'a list -> bool = <fun>
```

Patterns are *linear*: a variable cannot be bound several times by a given pattern. In particular, there is no way to test for equality between two parts of a data structure using only a pattern:

```h
# let pair_equal = function
| x, x -> true
| x, y -> false;;

Error: Variable x is bound several times in this matching
```

However, we can use a `when` guard for this purpose:

```h
# let pair_equal = function
| x, y when x = y -> true
| _ -> false;;
val pair_equal : 'a * 'a -> bool = <fun>
```

## Constant patterns

A pattern consisting in a constant matches the values that are equal to this constant.

```h
# let bool_of_string = function
| "true" -> true
| "false" -> false
| _ -> raise (Invalid_argument "bool_of_string");
val bool_of_string : string -> bool = <fun>
```

## Alias patterns

The pattern `pattern₁` as `value-name` matches the same values as `pattern₁`. If the matching against `pattern₁` is successful, the name `value-name` is bound to the matched value, in addition to the bindings performed by the matching against `pattern₁`.

```h
# let sort_pair ((x, y) as p) =
  if x <= y then p else (y, x);;
val sort_pair : 'a * 'a -> 'a * 'a = <fun>
```

## Parenthesized patterns

The pattern (`pattern₁`) matches the same values as `pattern₁`. A type constraint can appear in a parenthesized pattern, as in (`pattern₁`: `typexpr`). This constraint forces the type of `pattern₁` to be compatible with `typexpr`.

```h
# let int_triple_is_ordered ((a, b, c) : int * int * int) =
  a <= b && b <= c;;
val int_triple_is_ordered : int * int * int -> bool = <fun>
```
matching. Optionally, a record pattern can be terminated by `;_` to convey the fact that not all fields of the record type are listed in the record pattern and that it is intentional. Optional type constraints can be added field by field with `{ field₁ : typexpr₁ = pattern₁ ; ... ; fieldₙ : typexprₙ = patternₙ }` to force the type of `fieldₖ` to be compatible with `typexprₖ`.

```h
# let bytes_allocated
{
  Gc.minor_words = minor;
  Gc.major_words = major;
  Gc.promoted_words = prom;
}
=
(
  (Sys.word_size / 4) * int_of_float (minor +. major -. prom);
)
val bytes_allocated : Gc.stat -> int = <fun>
```

## Array patterns

The pattern `[| pattern₁ ; ... ; patternₙ |]` matches arrays of length *n* such that the *i*-th array element matches the pattern *pattern*ᵢ, for *i* = 1, ..., *n*.

```h
# let matrix3_is_symmetric = function
| [[|_; b; c|];
  [|d; _; f|];
  [[|g; h; _|]|] -> b = d && c = g && f = h
| _ -> failwith "matrix3_is_symmetric: not a 3x3 matrix";;
val matrix3_is_symmetric : 'a array array -> bool = <fun>
```

## Range patterns

The pattern `'c' .. 'd'` is a shorthand for the pattern

`'c' | 'c₁' | 'c₂' | ... | 'cₙ' | 'd'`

where `c₁, c₂, ..., cₙ` are the characters that occur between `c` and `d` in the ASCII character set. For instance, the pattern `'0'..'9'` matches all characters that are digits.

```h
# type char_class = Uppercase | Lowercase | Digit | Other

let classify_char = function
| 'A'..'Z' -> Uppercase
| 'a'..'z' -> Lowercase
| '0'..'9' -> Digit
| _ -> Other;;

type char_class = Uppercase | Lowercase | Digit | Other
val classify_char : char -> char_class = <fun>
```
## "Or" patterns

The pattern `pattern₁ | pattern₂` represents the logical "or" of the two patterns `pattern₁` and `pattern₂`. A value matches `pattern₁ | pattern₂` if it matches `pattern₁` or `pattern₂`. The two sub-patterns `pattern₁` and `pattern₂` must bind exactly the same identifiers to values having the same types. Matching is performed from left to right. More precisely, in case some value `v` matches `pattern₁ | pattern₂`, the bindings performed are those of `pattern₁` when `v` matches `pattern₁`. Otherwise, value `v` matches `pattern₂` whose bindings are performed.

``` OCaml
# type shape = Square of float | Rect of (float * float) | Circle of float

let isRectangular = function
| Square _ | Rect _ -> true
| Circle _ -> false;;

type shape = Square of float | Rect of (float * float) | Circle of float
val isRectangular : shape -> bool = <fun>
```

## Variant patterns

The pattern `constr ( pattern₁ , ..., patternₙ )` matches all variants whose constructor is equal to `constr`, and whose arguments match `pattern₁...patternₙ`. It is a type error if `n` is not the number of arguments expected by the constructor.

The pattern `constr _` matches all variants whose constructor is `constr`.

``` OCaml
# type 'a tree = Lf | Br of 'a tree * 'a * 'a tree

let rec total = function
| Br (l, x, r) -> total l + x + total r
| Lf -> 0;;

type 'a tree = Lf | Br of 'a tree * 'a * 'a tree
val total : int tree -> int = <fun>
```

The pattern `pattern₁::: pattern₂` matches non-empty lists whose heads match `pattern₁`, and whose tails match `pattern₂`.

The pattern `[ pattern₁ ; ... ; patternₙ ]` matches lists of length `n` whose elements match `pattern₁ ... patternₙ`, respectively. This pattern behaves like `pattern₁::: ... ::: patternₙ :: []`.

``` OCaml
# let rec destutter = function
| [] -> []
| [a] -> [a]
| a :: b :: t -> if a = b then destutter (b :: t) else a :: destutter (b :: t);;

val destutter : 'a list -> 'a list = <fun>
```

## Polymorphic variant patterns

The pattern `tag-name pattern₁` matches all polymorphic variants whose tag is equal to `tag-name`, and whose argument matches `pattern₁`.
### 11.6.1 Lazy patterns

(Introduced in Objective Caml 3.11)

pattern ::= ...

The pattern lazy pattern matches a value v of type Lazy.t, provided pattern matches the result of forcing v with Lazy.force. A successful match of a pattern containing lazy sub-patterns forces the corresponding parts of the value being matched, even those that imply no test such as lazy value-name or lazy _ . Matching a value with a pattern-matching where some patterns contain lazy sub-patterns may imply forcing parts of the value, even when the pattern selected in the end has no lazy sub-pattern.

```ocaml
# let force_opt = function
| Some (lazy n) -> n
| None -> 0;;
val force_opt : int lazy_t option -> int = <fun>
```

For more information, see the description of module Lazy in the standard library (module Lazy[28.29]).

#### Exception patterns

(Introduced in OCaml 4.02)

A new form of exception pattern, exception pattern, is allowed only as a toplevel pattern or inside a toplevel or-pattern under a match...with pattern-matching (other occurrences are rejected by the type-checker).

Cases with such a toplevel pattern are called “exception cases”, as opposed to regular “value cases”. Exception cases are applied when the evaluation of the matched expression raises an exception. The exception value is then matched against all the exception cases and re-raised if none of them accept the exception (as with a try...with block). Since the bodies of all exception and value cases are outside the scope of the exception handler, they are all considered to be in tail-position: if the match...with block itself is in tail position in the current function, any function call in tail position in one of the case bodies results in an actual tail call.

A pattern match must contain at least one value case. It is an error if all cases are exceptions, because there would be no code to handle the return of a value.

```ocaml
# let find_opt p l =
  match List.find p l with
  | exception Not_found -> None
  | x -> Some x;;
val find_opt : ('a -> bool) -> 'a list -> 'a option = <fun>
```

#### Local opens for patterns

(Introduced in OCaml 4.04)

For patterns, local opens are limited to the module-path . ( pattern ) construction. This construction locally opens the module referred to by the module path module-path in the scope of the pattern pattern .
```h
# let rec split = function
| [] -> ([], [])
| h :: t ->
    let ss, gs = split t in
    match h with
    | `Sheep _ as s -> (s :: ss, gs)
    | `Goat _ as g -> (ss, g :: gs);;
val split :
    [< `Goat of 'a | `Sheep of 'b ] list ->
    [> `Sheep of 'b ] list * [> `Goat of 'a ] list = <fun>
```

## Polymorphic variant abbreviation patterns

If the type `[('a', 'b', ...)] typeconstr = [ `tag-name₁ typexpr₁ | ... | `tag-nameₙ typexprₙ ]` is defined, then the pattern `# typeconstr` is a shorthand for the following or-pattern: `( `tag-name₁ (`_` : typexpr₁`) | ... | `tag-nameₙ` (`_` : typexprₙ`) )`. It matches all values of type `[< typeconstr ]`.

```h
# type 'a rectangle = [ `Square of 'a | `Rectangle of 'a * 'a]
type 'a shape = [ `Circle of 'a | 'a rectangle]

let tryrectangle = function
| #rectangle as r -> Some r
| `Circle _ -> None;;

type 'a rectangle = [ `Rectangle of 'a * 'a | `Square of 'a ]
type 'a shape = [ `Circle of 'a | `Rectangle of 'a * 'a | `Square of 'a ]
val tryrectangle :
    [< `Circle of 'a | `Rectangle of 'b * 'b | `Square of 'b ] ->
    [> `Rectangle of 'b * 'b | `Square of 'b ] option = <fun>
```

## Tuple patterns

The pattern `pattern₁, ..., patternₙ` matches `n`-tuples whose components match the patterns `pattern₁` through `patternₙ`. That is, the pattern matches the tuple values `(v₁, ..., vₙ)` such that `patternᵢ` matches `vᵢ` for `i = 1, ..., n`.

```h
# let vector (x0, y0) (x1, y1) =
    (x1 - . x0, y1 - . y0);;
val vector : float * float -> float * float -> float * float = <fun>
```

## Record patterns

The pattern `{ field₁ [= pattern₁] ; ... ; fieldₙ [= patternₙ] }` matches records that define at least the fields `field₁` through `fieldₙ`, and such that the value associated to `fieldᵢ` matches the pattern `patternᵢ`, for `i = 1, ..., n`. A single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, and a single qualified identifier `module-path`. `fieldₖ` stands for `module-path`. `fieldₖ = fieldₖ`. The record value can define more fields than `field₁ ... fieldₙ`; the values associated to these extra fields are not taken into account for
When the body of a local open pattern is delimited by [ ], [ | ], or { }, the parentheses can be omitted. For example, *module-path* . [ *pattern* ] is equivalent to *module-path* . ([ *pattern* ]), and *module-path* . [ | *pattern* | ] is equivalent to *module-path* . ([ | *pattern* |]).

# let bytes_allocated Gc.{minor_words; major_words; promoted_words; _} = (Sys.word_size / 4)
* int_of_float (minor_words +. major_words -. promoted_words);;
val bytes_allocated : Gc.stat -> int = <fun>
matching. Optionally, a record pattern can be terminated by `;_` to convey the fact that not all fields of the record type are listed in the record pattern and that it is intentional. Optional type constraints can be added field by field with `{ field₁ : typexpr₁ = pattern₁ ; ... ; fieldₙ : typexprₙ = patternₙ }` to force the type of `fieldₖ` to be compatible with `typexprₖ`.

```ocaml
# let bytes_allocated
    {Gc.minor_words = minor;
     Gc.major_words = major;
     Gc.promoted_words = prom;
    }
    =
    (Sys.word_size / 4) * int_of_float (minor +. major -. prom);
val bytes_allocated : Gc.stat -> int = <fun>
```

## Array patterns

The pattern `[| pattern₁ ; ... ; patternₙ |]` matches arrays of length *n* such that the *i*-th array element matches the pattern *pattern*ᵢ, for *i* = 1, ..., *n*.

```ocaml
# let matrix3_is_symmetric = function
  | [[|_; b; c|];
    [|d; _; f|];
    [[|g; h; _|]|] -> b = d && c = g && f = h
  | _ -> failwith "matrix3_is_symmetric: not a 3x3 matrix";;
val matrix3_is_symmetric : 'a array array -> bool = <fun>
```

## Range patterns

The pattern `'c' .. 'd'` is a shorthand for the pattern

`'c' | 'c₁' | 'c₂' | ... | 'cₙ' | 'd'`

where `c₁`, `c₂`, ..., `cₙ` are the characters that occur between `c` and `d` in the ASCII character set. For instance, the pattern `'0'..'9'` matches all characters that are digits.

```ocaml
# type char_class = Uppercase | Lowercase | Digit | Other
```

```ocaml
let classify_char = function
```

```ocaml
| 'A'..'Z' -> Uppercase
| 'a'..'z' -> Lowercase
| '0'..'9' -> Digit
| _ -> Other;;
```

```ocaml
type char_class = Uppercase | Lowercase | Digit | Other
```

```ocaml
val classify_char : char -> char_class = <fun>
```
## 11.7 Expressions

expr ::= value-path
| constant
| ( expr )
| begin expr end
| ( expr : typexpr )
| expr {, expr }+
| constr expr
| ` tag-name expr
| expr :: expr
| [ expr {; expr } [;]]
| [| expr {; expr } [;]|]
| { field [: typexpr ] [= expr ] {; field [: typexpr ] [= expr ]} [;] }
| { expr with field [: typexpr ] [= expr ] {; field [: typexpr ] [= expr ]} [;] }
| expr {argument}+
| prefix-symbol expr
| - expr
| -. expr
| expr infix-op expr
| expr . field
| expr . field <- expr
| expr . ( expr )
| expr . ( expr ) <- expr
| expr . [ expr ]
| expr . [ expr ] <- expr
| if expr then expr [else expr]
| while expr do expr done
| for value-name = expr (to | downto) expr do expr done
| expr ; expr
| match expr with pattern-matching
| function pattern-matching
| fun {parameter}+ [: typexpr ] -> expr
| try expr with pattern-matching
| let [rec] let-binding {and let-binding} in expr
| let exception constr-decl in expr
| let module module-name { ( module-name : module-type ) } [: module-type ]
| = module-expr in expr
| ( expr :> typexpr )
| ( expr : typexpr :> typexpr )
| assert expr
| lazy expr
| local-open
| object-expr
### 11.6.1 Lazy patterns

(Introduced in Objective Caml 3.11)

The pattern lazy pattern matches a value *v* of type Lazy.t, provided pattern matches the result of forcing *v* with Lazy.force. A successful match of a pattern containing lazy sub-patterns forces the corresponding parts of the value being matched, even those that imply no test such as lazy *value-name* or lazy _*. Matching a value with a *pattern-matching* where some patterns contain lazy sub-patterns may imply forcing parts of the value, even when the pattern selected in the end has no lazy sub-pattern.

```hkl
# let force_opt = function
| Some (lazy n) -> n
| None -> 0;
val force_opt : int lazy_t option -> int = <fun>
```

For more information, see the description of module Lazy in the standard library (module Lazy[29.31]).

### Exception patterns

(Introduced in OCaml 4.02)

A new form of exception pattern, exception pattern, is allowed only as a toplevel pattern or inside a toplevel or-pattern under a match...with pattern-matching (other occurrences are rejected by the type-checker).

Cases with such a toplevel pattern are called “exception cases”, as opposed to regular “value cases”. Exception cases are applied when the evaluation of the matched expression raises an exception. The exception value is then matched against all the exception cases and re-raised if none of them accept the exception (as with a try...with block). Since the bodies of all exception and value cases are outside the scope of the exception handler, they are all considered to be in tail-position: if the match...with block itself is in tail position in the current function, any function call in tail position in one of the case bodies results in an actual tail call.

A pattern match must contain at least one value case. It is an error if all cases are exceptions, because there would be no code to handle the return of a value.

```hkl
# let find_opt p l =
  match List.find p l with
  | exception Not_found -> None
  | x -> Some x;
val find_opt : ('a -> bool) -> 'a list -> 'a option = <fun>
```

### Local opens for patterns

(Introduced in OCaml 4.04)

For patterns, local opens are limited to the module-path .( pattern ) construction. This construction locally opens the module referred to by the module path module-path in the scope of the pattern pattern.
<table><tr><td>argument</td><td>::=</td><td>expr<br/>| ~ label-name<br/>| ~ label-name : expr<br/>| ? label-name<br/>| ? label-name : expr</td></tr><tr><td>pattern-matching</td><td>::=</td><td>[|] pattern [when expr] -> expr { | pattern [when expr] -> expr }</td></tr><tr><td>let-binding</td><td>::=</td><td>pattern = expr<br/>| value-name {parameter} [: typexpr] [:=> typexpr] = expr<br/>| value-name : poly-typexpr = expr</td></tr><tr><td>parameter</td><td>::=</td><td>pattern<br/>| ~ label-name<br/>| ~ ( label-name [: typexpr] )<br/>| ~ label-name : pattern<br/>| ? label-name<br/>| ? ( label-name [: typexpr] [= expr] )<br/>| ? label-name : pattern<br/>| ? label-name : ( pattern [: typexpr] [= expr] )</td></tr><tr><td>local-open</td><td>::=</td><td>let open module-path in expr<br/>| module-path . ( expr )<br/>| module-path . [ expr ]<br/>| module-path . [ | expr |]<br/>| module-path . { expr }<br/>| module-path . {&lt; expr &gt;}</td></tr><tr><td>object-expr</td><td>::=</td><td>new class-path<br/>| object class-body end<br/>| expr # method-name<br/>| inst-var-name<br/>| inst-var-name &lt;- expr<br/>| {&lt; [inst-var-name [= expr] {; inst-var-name [= expr]} [;]] &gt;}</td></tr></table>

See also the following language extensions: first-class modules, overriding in open statements, syntax for Bigarray access, attributes, extension nodes and extended indexing operators.

## 11.7.1 Precedence and associativity

The table below shows the relative precedences and associativity of operators and non-closed constructions. The constructions with higher precedence come first. For infix and prefix symbols, we write "*..." to mean "any symbol starting with *".
When the body of a local open pattern is delimited by `[]`, `[] |`], or `{ }`, the parentheses can be omitted. For example, `module-path . [ pattern ]` is equivalent to `module-path . ([ pattern ])`, and `module-path . [ | pattern |]` is equivalent to `module-path . ([| pattern |])`.

```ocaml
# let bytes_allocated Gc.{minor_words; major_words; promoted_words; _} =
    (Sys.word_size / 4)
* int_of_float (minor_words +. major_words -. promoted_words);;
val bytes_allocated : Gc.stat -> int = <fun>
```
<table><thead><tr><th>Construction or operator</th><th>Associativity</th></tr></thead><tbody><tr><td>prefix-symbol</td><td>-</td></tr><tr><td>. . ( . [ . { (see section 12.11)</td><td>-</td></tr><tr><td>#!</td><td>left</td></tr><tr><td>function application, constructor application, tag application, assert, lazy</td><td>left</td></tr><tr><td>- -. (prefix)</td><td>-</td></tr><tr><td>**... lsl lsr asr</td><td>right</td></tr><tr><td>*... /... %... mod land lor lxor</td><td>left</td></tr><tr><td>+... -...</td><td>left</td></tr><tr><td>::</td><td>right</td></tr><tr><td>@... ^...</td><td>right</td></tr><tr><td>=... <... >... |... &... $... !=</td><td>left</td></tr><tr><td>& &amp;</td><td>right</td></tr><tr><td>or ||</td><td>right</td></tr><tr><td>,</td><td>-</td></tr><tr><td>&lt;= :=</td><td>right</td></tr><tr><td>if</td><td>-</td></tr><tr><td>;</td><td>right</td></tr><tr><td>let match fun function try</td><td>-</td></tr></tbody></table>

It is simple to test or refresh one's understanding:

# 3 + 3 mod 2, 3 + (3 mod 2), (3 + 3) mod 2;;

- : int * int * int = (4, 4, 0)

## 11.7.2 Basic expressions

### Constants

An expression consisting in a constant evaluates to this constant. For example, 3.14 or [||].

### Value paths

An expression consisting in an access path evaluates to the value bound to this path in the current evaluation environment. The path can be either a value name or an access path to a value component of a module.

# Floatolaola labels to list;;

- : Floatolaola labels.t -> float list = <fun>

### Parenthesized expressions

The expressions ( expr ) and begin expr end have the same value as expr . The two constructs are semantically equivalent, but it is good style to use begin...end inside control structures:

if ... then begin ... ; ... end else begin ... ; ... end

and (...) for the other grouping situations.
11.7 Expressions

expr ::= value-path
| constant
| ( expr )
| begin expr end
| ( expr : typexpr )
| expr {, expr }+
| constr expr
| ` tag-name expr
| expr :: expr
| [ expr {; expr } [;] ]
| [ | expr {; expr } [;] | ]
| { field [ : typexpr ] [= expr ] {; field [ : typexpr ] [= expr ]} [;] }
| { expr with field [ : typexpr ] [= expr ] {; field [ : typexpr ] [= expr ]} [;] }
| expr {argument}+
| prefix-symbol expr
| - expr
| -. expr
| expr infix-op expr
| expr . field
| expr . field <- expr
| expr . ( expr )
| expr . ( expr ) <- expr
| expr . [ expr ]
| expr . [ expr ] <- expr
| if expr then expr [else expr]
| while expr do expr done
| for value-name = expr (to | downto) expr do expr done
| expr ; expr
| match expr with pattern-matching
| function pattern-matching
| fun {parameter}+ [ : typexpr ] -> expr
| try expr with pattern-matching
| let [rec] let-binding {and let-binding} in expr
| let exception constr-decl in expr
| let module module-name { ( module-name : module-type ) } [ : module-type ]
| = module-expr in expr
| ( expr :> typexpr )
| ( expr : typexpr :> typexpr )
| assert expr
| lazy expr
| local-open
| object-expr
```pascal
# let x = 1 + 2 * 3
let y = (1 + 2) * 3;;
val x : int = 7
val y : int = 9

# let f a b =
  if a = b then
    print_endline "Equal"
  else begin
    print_string "Not Equal: ";
    print_int a;
    print_string " and ";
    print_int b;
    print_newline ()
  end;;

val f : int -> int -> unit = <fun>
```

Parenthesized expressions can contain a type constraint, as in `( expr : typexpr )`. This constraint forces the type of `expr` to be compatible with `typexpr`.

Parenthesized expressions can also contain coercions (`expr [: typexpr] :> typexpr`) (see subsection 11.7.9 below).

## Function application

Function application is denoted by juxtaposition of (possibly labeled) expressions. The expression `expr argument₁ ... argumentₙ` evaluates the expression `expr` and those appearing in `argument₁` to `argumentₙ`. The expression `expr` must evaluate to a functional value `f`, which is then applied to the values of `argument₁`, ..., `argumentₙ`.

The order in which the expressions `expr`, `argument₁`, ..., `argumentₙ` are evaluated is not specified.

```pascal
# List.fold_left (+) 0 [1; 2; 3; 4; 5];;
- : int = 15
```

Arguments and parameters are matched according to their respective labels. Argument order is irrelevant, except among arguments with the same label, or no label.

```pascal
# ListLabels.fold_left ~f:( @ ) ~init:[] [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]];;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
```

If a parameter is specified as optional (label prefixed by ?) in the type of `expr`, the corresponding argument will be automatically wrapped with the constructor `Some`, except if the argument itself is also prefixed by ?, in which case it is passed as is.

```pascal
# letfullname ?title first second =
  match title with
  | Some t -> t ^ " " ^ first ^ " " ^ second
  | None -> first ^ " " ^ second
```
argument ::= expr
           | ~ label-name
           | ~ label-name : expr
           | ? label-name
           | ? label-name : expr

pattern-matching ::= [|] pattern [when expr] -> expr { | pattern [when expr] -> expr }

let-binding ::= pattern = expr
               | value-name {parameter} [: typexpr] [:= typexpr] = expr
               | value-name : poly-typexpr = expr

parameter ::= pattern
               | ~ label-name
               | ~ ( label-name [: typexpr ] )
               | ~ label-name : pattern
               | ? label-name
               | ? ( label-name [: typexpr ] [= expr ] )
               | ? label-name : pattern
               | ? label-name : ( pattern [: typexpr ] [= expr ] )

local-open ::=
               | let open module-path in expr
               | module-path . ( expr )
               | module-path . [ expr ]
               | module-path . [ | expr | ]
               | module-path . { expr }
               | module-path . { < expr > }

object-expr ::=
               | new class-path
               | object class-body end
               | expr # method-name
               | inst-var-name
               | inst-var-name <- expr
               | { < [ inst-var-name [= expr ] { ; inst-var-name [= expr ] } [ ; ] > }

See also the following language extensions: first-class modules, overriding in open statements, syntax for Bigarray access, attributes, extension nodes, extended indexing operators, type-directed disambiguation of array literals, and labeled tuples.

11.7.1 Precedence and associativity

The table below shows the relative precedences and associativity of operators and non-closed
constructions. The constructions with higher precedence come first. For infix and prefix symbols,
we write "*..." to mean "any symbol starting with *".
let name =fullname ~title:"Mrs" "Jane" "Fisher"

let address ?title first second town =

fullname ?title first second ^ "\n" ^ town;;

valfullname: ?title: string -> string -> string -> string = <fun>

val name : string = "Mrs Jane Fisher"

val address : ?title: string -> string -> string -> string -> string = <fun>

If a non-labeled argument is passed, and its corresponding parameter is preceded by one or
several optional parameters, then these parameters are defaulted, i.e. the value None will be passed
for them. All other missing parameters (without corresponding argument), both optional and
non-optional, will be kept, and the result of the function will still be a function of these missing
parameters to the body of f.

# letfullname ?title first second =

match title with

| Some t -> t ^ " " ^ first ^ " " ^ second

| None -> first ^ " " ^ second

let name =fullname "Jane" "Fisher";;

valfullname: ?title: string -> string -> string -> string = <fun>

val name : string = "Jane Fisher"

In all cases but exact match of order and labels, without optional parameters, the function
type should be known at the application point. This can be ensured by adding a type constraint.
Principality of the derivation can be checked in the -principal mode.

As a special case, OCaml supports labels-omitted full applications: if the function has a
known arity, all the arguments are unlabeled, and their number matches the number of non-optional
parameters, then labels are ignored and non-optional parameters are matched in their definition
order. Optional arguments are defaulted. This omission of labels is discouraged and results in a
warning, see 13.5.1.

Function definition

Two syntactic forms are provided to define functions. The first form is introduced by the keyword
function :

function pattern₁ -> expr₁
| ...
| patternₙ -> exprₙ

This expression evaluates to a functional value with one argument. When this function is applied to a value v, this value is matched against each pattern pattern₁ to patternₙ. If one of these matchings succeeds, that is, if the value v matches the pattern patternᵢ for some i, then the expression exprᵢ associated to the selected pattern is evaluated, and its value becomes the value of the function application. The evaluation of exprᵢ takes place in an environment enriched by the bindings performed during the matching.

If several patterns match the argument v, the one that occurs first in the function definition is
selected. If none of the patterns matches the argument, the exception Match_failure is raised.
<table><thead><tr><th>Construction or operator</th><th>Associativity</th></tr></thead><tbody><tr><td>prefix-symbol</td><td>-</td></tr><tr><td>. .( . .[ . .{ (see section 12.11)</td><td>-</td></tr><tr><td>#...</td><td>left</td></tr><tr><td>function application, constructor application, tag application, assert, lazy</td><td>left</td></tr><tr><td>- -. (prefix)</td><td>-</td></tr><tr><td>**... lsl lsr asr</td><td>right</td></tr><tr><td>*... /... %... mod land lor lxor</td><td>left</td></tr><tr><td>+... -...</td><td>left</td></tr><tr><td>::</td><td>right</td></tr><tr><td>@... ^...</td><td>right</td></tr><tr><td>=... <... >... |... &... $... !=</td><td>left</td></tr><tr><td>& &amp;</td><td>right</td></tr><tr><td>or ||</td><td>right</td></tr><tr><td>,</td><td>-</td></tr><tr><td>&lt;= :=</td><td>right</td></tr><tr><td>if</td><td>-</td></tr><tr><td>;</td><td>right</td></tr><tr><td>let match fun function try</td><td>-</td></tr></tbody></table>

It is simple to test or refresh one's understanding:

# 3 + 3 mod 2, 3 + (3 mod 2), (3 + 3) mod 2;;

- : int * int * int = (4, 4, 0)

## 11.7.2 Basic expressions

### Constants

An expression consisting in a constant evaluates to this constant. For example, 3.14 or [11].

### Value paths

An expression consisting in an access path evaluates to the value bound to this path in the current evaluation environment. The path can be either a value name or an access path to a value component of a module.

# Floatola. ArrayLabels. to_list;;

- : Float. ArrayLabels.t -> float list = <fun>

### Parenthesized expressions

The expressions ( expr ) and begin expr end have the same value as expr . The two constructs are semantically equivalent, but it is good style to use begin...end inside control structures:

if ... then begin ... ; ... end else begin ... ; ... end

and (...) for the other grouping situations.
```h
# (function (0, 0) -> "both zero"
| (0,_) -> "first only zero"
| (_ , 0) -> "second only zero"
| (_ ,_) -> "neither zero")
(7, 0);;
- : string = "second only zero"
```

The other form of function definition is introduced by the keyword `fun`:

`fun parameter₁...parameterₙ -> expr`

This expression is equivalent to:

`fun parameter₁ -> ...fun parameterₙ -> expr`

```h
# let f = (fun a -> fun b -> fun c -> a + b + c)
let g = (fun a b c -> a + b + c);;
val f : int -> int -> int -> int = <fun>
val g : int -> int -> int -> int = <fun>
```

An optional type constraint `typexpr` can be added before `->` to enforce the type of the result to be compatible with the constraint `typexpr`:

`fun parameter₁...parameterₙ : typexpr -> expr`

is equivalent to

`fun parameter₁ -> ...fun parameterₙ -> (expr : typexpr)`

Beware of the small syntactic difference between a type constraint on the last parameter

`fun parameter₁... (parameterₙ : typexpr) -> expr`

and one on the result

`fun parameter₁...parameterₙ : typexpr -> expr`

```h
# let eq = fun (a : int) (b : int) -> a = b
let eq2 = fun a b : bool -> a = b
let eq3 = fun (a : int) (b : int) : bool -> a = b;;
val eq : int -> int -> bool = <fun>
val eq2 : 'a -> 'a -> bool = <fun>
val eq3 : int -> int -> bool = <fun>
```

The parameter patterns `~ lab` and `~ (lab [: typ])` are shorthands for respectively `~ lab : lab` and `~ lab : (lab [: typ])`, and similarly for their optional counterparts.

```h
# let bool_map ~cmp:(cmp : int -> int -> bool) 1 =
  List.map cmp 1

let bool_map' ~ (cmp : int -> int -> bool) 1 =
  List.map cmp 1;;
```
``` OCaml
# let x = 1 + 2 * 3
let y = (1 + 2) * 3;;
val x : int = 7
val y : int = 9

# let f a b =
  if a = b then
    print_endline "Equal"
  else begin
    print_string "Not Equal: ";
    print_int a;
    print_string " and ";
    print_int b;
    print_newline ()
  end;;

val f : int -> int -> unit = <fun>
```

Parenthesized expressions can contain a type constraint, as in `( expr : typexpr )`. This constraint forces the type of `expr` to be compatible with `typexpr`.

Parenthesized expressions can also contain coercions (`expr [: typexpr] :> typexpr`) (see subsection 11.7.9 below).

## Function application

Function application is denoted by juxtaposition of (possibly labeled) expressions. The expression `expr argument₁ ... argumentₙ` evaluates the expression `expr` and those appearing in `argument₁` to `argumentₙ`. The expression `expr` must evaluate to a functional value `f`, which is then applied to the values of `argument₁`, ..., `argumentₙ`.

The order in which the expressions `expr`, `argument₁`, ..., `argumentₙ` are evaluated is not specified.

``` OCaml
# List.fold_left (+) 0 [1; 2; 3; 4; 5];;
- : int = 15
```

Arguments and parameters are matched according to their respective labels. Argument order is irrelevant, except among arguments with the same label, or no label.

``` OCaml
# ListLabels.fold_left ~f:( @ ) ~init:[] [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]];;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
```

If a parameter is specified as optional (label prefixed by ?) in the type of `expr`, the corresponding argument will be automatically wrapped with the constructor `Some`, except if the argument itself is also prefixed by ?, in which case it is passed as is.

``` OCaml
# letfullname ?title first second =
  match title with
  | Some t -> t ^ " " ^ first ^ " " ^ second
  | None -> first ^ " " ^ second

let name =fullname ~title:"Mrs" "Jane" "Fisher"
```
```ocaml
val bool_map : cmp:(int -> int -> bool) -> int list -> (int -> bool) list =
<fun>
val bool_map' : cmp:(int -> int -> bool) -> int list -> (int -> bool) list =
<fun>
```

A function of the form `fun ? lab : ( pattern = expr₀ ) -> expr` is equivalent to `fun ? lab : ident -> let pattern = match ident with Some ident -> ident | None -> expr₀ in expr` where `ident` is a fresh variable, except that it is unspecified when `expr₀` is evaluated.

```ocaml
# let open_file_for_input ?binary filename =
    match binary with
    | Some true -> open_in_bin filename
    | Some false | None -> open_in filename

let open_file_for_input' ?(binary=false) filename =
    if binary then open_in_bin filename else open_in filename;;
val open_file_for_input : ?binary:bool -> string -> in_channel = <fun>
val open_file_for_input' : ?binary:bool -> string -> in_channel = <fun>
```

After these two transformations, expressions are of the form

`fun [label₁] pattern₁ -> ... fun [labelₙ] patternₙ -> expr`

If we ignore labels, which will only be meaningful at function application, this is equivalent to

`function pattern₁ -> ... function patternₙ -> expr`

That is, the `fun` expression above evaluates to a curried function with `n` arguments: after applying this function `n` times to the values `v₁...vₙ`, the values will be matched in parallel against the patterns `pattern₁...patternₙ`. If the matching succeeds, the function returns the value of `expr` in an environment enriched by the bindings performed during the matchings. If the matching fails, the exception `Match_failure` is raised.

## Guards in pattern-matchings

The cases of a pattern matching (in the `function`, `match` and `try` constructs) can include guard expressions, which are arbitrary boolean expressions that must evaluate to `true` for the match case to be selected. Guards occur just before the `->` token and are introduced by the `when` keyword:

``` Ocaml
function pattern₁ [when cond₁] -> expr₁
  | ...
  | patternₙ [when condₙ] -> exprₙ
```

Matching proceeds as described before, except that if the value matches some pattern `patternᵢ` which has a guard `condᵢ`, then the expression `condᵢ` is evaluated (in an environment enriched by the bindings performed during matching). If `condᵢ` evaluates to `true`, then `exprᵢ` is evaluated and its value returned as the result of the matching, as usual. But if `condᵢ` evaluates to `false`, the matching is resumed against the patterns following `patternᵢ`.
```hml
let address ?title first second town =
   fullname ?title first second ^ "\n" ^ town;;

valfullname : ?title: string -> string -> string -> string = <fun>
val name : string = "Mrs Jane Fisher"

val address : ?title: string -> string -> string -> string -> string = <fun>
```

If a non-labeled argument is passed, and its corresponding parameter is preceded by one or several optional parameters, then these parameters are *defaulted*, i.e. the value `None` will be passed for them. All other missing parameters (without corresponding argument), both optional and non-optional, will be kept, and the result of the function will still be a function of these missing parameters to the body of `f`.

```hml
# letfullname ?title first second =
    match title with
    | Some t -> t ^ " " ^ first ^ " " ^ second
    | None -> first ^ " " ^ second

let name =fullname "Jane" "Fisher";;

valfullname : ?title: string -> string -> string -> string = <fun>
val name : string = "Jane Fisher"
```

In all cases but exact match of order and labels, without optional parameters, the function type should be known at the application point. This can be ensured by adding a type constraint. Principality of the derivation can be checked in the `-principal` mode.

As a special case, OCaml supports *labels-omitted* full applications: if the function has a known arity, all the arguments are unlabeled, and their number matches the number of non-optional parameters, then labels are ignored and non-optional parameters are matched in their definition order. Optional arguments are defaulted. This omission of labels is discouraged and results in a warning, see 13.5.1.

## Function definition

Two syntactic forms are provided to define functions. The first form is introduced by the keyword `function`:

```hml
function pattern_1 -> expr_1
| ...
| pattern_n -> expr_n
```

This expression evaluates to a functional value with one argument. When this function is applied to a value `v`, this value is matched against each pattern `pattern_1` to `pattern_n`. If one of these matchings succeeds, that is, if the value `v` matches the pattern `pattern_i` for some `i`, then the expression `expr_i` associated to the selected pattern is evaluated, and its value becomes the value of the function application. The evaluation of `expr_i` takes place in an environment enriched by the bindings performed during the matching.

If several patterns match the argument `v`, the one that occurs first in the function definition is selected. If none of the patterns matches the argument, the exception `Match_failure` is raised.
```h
# let rec repeat f = function
| 0 -> ()
| n when n > 0 -> f (); repeat f (n - 1)
| _ -> raise (Invalid_argument "repeat");
val repeat : (unit -> 'a) -> int -> unit = <fun>
```

## Local definitions

The `let` and `let rec` constructs bind value names locally. The construct

`let pattern₁ = expr₁ and ... and patternₙ = exprₙ in expr`

evaluates `expr₁...exprₙ` in some unspecified order and matches their values against the patterns `pattern₁...patternₙ`. If the matchings succeed, `expr` is evaluated in the environment enriched by the bindings performed during matching, and the value of `expr` is returned as the value of the whole `let` expression. If one of the matchings fails, the exception `Match_failure` is raised.

```h
# let v =
let x = 1 in [x; x; x]

let v' =
let a, b = (1, 2) in a + b

let v'' =
let a = 1 and b = 2 in a + b;;

val v : int list = [1; 1; 1]
val v' : int = 3
val v'' : int = 3
```

An alternate syntax is provided to bind variables to functional values: instead of writing

`let ident = fun parameter₁...parameterₘ -> expr`

in a `let` expression, one may instead write

`let ident parameter₁...parameterₘ = expr`

```h
# let f = fun x -> fun y -> fun z -> x + y + z

let f' = fun x y z -> x + y + z

let f'' x y z = x + y + z;;

val f : int -> int -> int -> int = <fun>
val f' : int -> int -> int -> int = <fun>
val f'' : int -> int -> int -> int = <fun>
```

Recursive definitions of names are introduced by `let rec`:

`let rec pattern₁ = expr₁ and ... and patternₙ = exprₙ in expr`
```ocaml
# (function (0, 0) -> "both zero"
| (0,_) -> "first only zero"
| (_ , 0) -> "second only zero"
| (_ ,_) -> "neither zero")
(7, 0);;
- : string = "second only zero"
```

The other form of function definition is introduced by the keyword `fun`:

`fun parameter₁ ... parameterₙ -> expr`

This expression is equivalent to:

`fun parameter₁ -> ... fun parameterₙ -> expr`

```ocaml
# let f = (fun a -> fun b -> fun c -> a + b + c)
let g = (fun a b c -> a + b + c);;
val f : int -> int -> int -> int = <fun>
val g : int -> int -> int -> int = <fun>
```

An optional type constraint `typexpr` can be added before `->` to enforce the type of the result to be compatible with the constraint `typexpr`:

`fun parameter₁ ... parameterₙ : typexpr -> expr`

is equivalent to

`fun parameter₁ -> ... fun parameterₙ -> (expr : typexpr)`

Beware of the small syntactic difference between a type constraint on the last parameter

`fun parameter₁... (parameterₙ : typexpr) -> expr`

and one on the result

`fun parameter₁... parameterₙ : typexpr -> expr`

```ocaml
# let eq = fun (a : int) (b : int) -> a = b
let eq2 = fun a b : bool -> a = b
let eq3 = fun (a : int) (b : int) : bool -> a = b;;
val eq : int -> int -> bool = <fun>
val eq2 : 'a -> 'a -> bool = <fun>
val eq3 : int -> int -> bool = <fun>
```

The parameter patterns `~ lab` and `~ (lab [: typ])` are shorthands for respectively `~ lab : lab` and `~ lab : (lab [: typ])`, and similarly for their optional counterparts.

```ocaml
# let bool_map ~cmp:(cmp : int -> int -> bool) 1 =
  List.map cmp 1

let bool_map' ~ (cmp : int -> int -> bool) 1 =
  List.map cmp 1;;
```
The only difference with the `let` construct described above is that the bindings of names to values performed by the pattern-matching are considered already performed when the expressions `expr_1` to `expr_n` are evaluated. That is, the expressions `expr_1` to `expr_n` can reference identifiers that are bound by one of the patterns `pattern_1`, ..., `pattern_n`, and expect them to have the same value as in `expr`, the body of the `let rec` construct.

``` OCaml
# let rec even =
    function 0 -> true | n -> odd (n - 1)
and odd =
    function 0 -> false | n -> even (n - 1)
in
    even 1000;;
- : bool = true
```

The recursive definition is guaranteed to behave as described above if the expressions `expr_1` to `expr_n` are function definitions (`fun`... or `function`...), and the patterns `pattern_1`...`pattern_n` are just value names, as in:

```
let rec name1 = fun... and... and namen = fun... in expr
```

This defines `name1...name_n` as mutually recursive functions local to `expr`.

The behavior of other forms of `let rec` definitions is implementation-dependent. The current implementation also supports a certain class of recursive definitions of non-functional values, as explained in section 12.1.

### 11.7.3 Local exceptions

(Introduced in OCaml 4.04)

It is possible to define local exceptions in expressions: `let exception constr-decl in expr`.

``` OCaml
# let map_empty_oniris f l =
    let exception Negative in
    let aux x = if x < 0 then raise Negative else f x in
    try List.map aux l with Negative -> [];
val map_empty_oniris : (int -> 'a) -> int list -> 'a list = <fun>
```

The syntactic scope of the exception constructor is the inner expression, but nothing prevents exception values created with this constructor from escaping this scope. Two executions of the definition above result in two incompatible exception constructors (as for any exception definition). For instance:

``` OCaml
# let gen () = let exception A in A

let () = assert(gen () = gen ());
Exception: Assert_failure ("expr.etex", 3, 9).
```

### 11.7.4 Explicit polymorphic type annotations

(Introduced in OCaml 3.12)

Polymorphic type annotations in `let`-definitions behave in a way similar to polymorphic methods:
```hcl
val bool_map : cmp:(int -> int -> bool) -> int list -> (int -> bool) list =
<fun>
val bool_map' : cmp:(int -> int -> bool) -> int list -> (int -> bool) list =
<fun>
```

A function of the form `fun ? lab : ( pattern = expr₀ ) -> expr` is equivalent to `fun ? lab : ident -> let pattern = match ident with Some ident -> ident | None -> expr₀ in expr` where `ident` is a fresh variable, except that it is unspecified when `expr₀` is evaluated.

```hcl
# let open_file_for_input ?binary filename =
match binary with
| Some true -> open_in_bin filename
| Some false | None -> open_in filename

let open_file_for_input' ?(binary=false) filename =
  if binary then open_in_bin filename else open_in filename;;
val open_file_for_input : ?binary:bool -> string -> in_channel = <fun>
val open_file_for_input' : ?binary:bool -> string -> in_channel = <fun>
```

After these two transformations, expressions are of the form

`fun [label₁] pattern₁ -> ... fun [labelₙ] patternₙ -> expr`

If we ignore labels, which will only be meaningful at function application, this is equivalent to

`function pattern₁ -> ... function patternₙ -> expr`

That is, the `fun` expression above evaluates to a curried function with `n` arguments: after applying this function `n` times to the values `v₁...vₙ`, the values will be matched in parallel against the patterns `pattern₁...patternₙ`. If the matching succeeds, the function returns the value of `expr` in an environment enriched by the bindings performed during the matchings. If the matching fails, the exception `Match_failure` is raised.

## Guards in pattern-matchings

The cases of a pattern matching (in the `function`, `match` and `try` constructs) can include guard expressions, which are arbitrary boolean expressions that must evaluate to `true` for the match case to be selected. Guards occur just before the `->` token and are introduced by the `when` keyword:

```hcl
function pattern₁ [when cond₁] -> expr₁
  | ...
  | patternₙ [when condₙ] -> exprₙ
```

Matching proceeds as described before, except that if the value matches some pattern `patternᵢ` which has a guard `condᵢ`, then the expression `condᵢ` is evaluated (in an environment enriched by the bindings performed during matching). If `condᵢ` evaluates to `true`, then `exprᵢ` is evaluated and its value returned as the result of the matching, as usual. But if `condᵢ` evaluates to `false`, the matching is resumed against the patterns following `patternᵢ`.
let pattern₁ : typ₁... typₙ . typexpr = expr

These annotations explicitly require the defined value to be polymorphic, and allow one to use
this polymorphism in recursive occurrences (when using `let rec`). Note however that this is a
normal polymorphic type, unifiable with any instance of itself.

### 11.7.5 Control structures

#### Sequence

The expression `expr₁; expr₂` evaluates `expr₁` first, then `expr₂`, and returns the value of `expr₂`.

```hkl
# let print_pair (a, b) =
  print_string "(";
  print_string (string_of_int a);
  print_string ",";
  print_string (string_of_int b);
  print_endline ")";;
val print_pair : int * int -> unit = <fun>
```

#### Conditional

The expression `if expr₁ then expr₂ else expr₃` evaluates to the value of `expr₂` if `expr₁` evaluates to the boolean `true`, and to the value of `expr₃` if `expr₁` evaluates to the boolean `false`.

```hkl
# let rec factorial x =
  if x <= 1 then 1 else x * factorial (x - 1);;
val factorial : int -> int = <fun>
```

The `else expr₃` part can be omitted, in which case it defaults to `else ()`.

```hkl
# let debug = ref false

let log msg =
  if !debug then prerr_endline msg;;
val debug : bool ref = {contents = false}
val log : string -> unit = <fun>
```

#### Case expression

The expression

```hkl
match expr
  with pattern₁ -> expr₁
  | ...
  | patternₙ -> exprₙ
```

matches the value of `expr` against the patterns `pattern₁` to `patternₙ`. If the matching against `patternᵢ` succeeds, the associated expression `exprᵢ` is evaluated, and its value becomes the value of the whole `match` expression. The evaluation of `exprᵢ` takes place in an environment enriched by
```ocaml
# let rec repeat f = function
| 0 -> ()
| n when n > 0 -> f (); repeat f (n - 1)
| _ -> raise (Invalid_argument "repeat");
val repeat : (unit -> 'a) -> int -> unit = <fun>
```

## Local definitions

The `let` and `let rec` constructs bind value names locally. The construct

`let pattern₁ = expr₁ and ... and patternₙ = exprₙ in expr`

evaluates `expr₁...exprₙ` in some unspecified order and matches their values against the patterns `pattern₁...patternₙ`. If the matchings succeed, `expr` is evaluated in the environment enriched by the bindings performed during matching, and the value of `expr` is returned as the value of the whole `let` expression. If one of the matchings fails, the exception `Match_failure` is raised.

```ocaml
# let v =
let x = 1 in [x; x; x]

let v' =
let a, b = (1, 2) in a + b

let v'' =
let a = 1 and b = 2 in a + b;;
val v : int list = [1; 1; 1]
val v' : int = 3
val v'' : int = 3
```

An alternate syntax is provided to bind variables to functional values: instead of writing

`let ident = fun parameter₁...parameterₘ -> expr`

in a `let` expression, one may instead write

`let ident parameter₁...parameterₘ = expr`

```ocaml
# let f = fun x -> fun y -> fun z -> x + y + z

let f' = fun x y z -> x + y + z

let f'' x y z = x + y + z;;
val f : int -> int -> int -> int = <fun>
val f' : int -> int -> int -> int = <fun>
val f'' : int -> int -> int -> int = <fun>
```

Recursive definitions of names are introduced by `let rec`:

`let rec pattern₁ = expr₁ and ... and patternₙ = exprₙ in expr`
the bindings performed during matching. If several patterns match the value of `expr`, the one that occurs first in the match expression is selected.

``` OCaml
# let rec sum l =
    match l with
    | [] -> 0
    | h :: t -> h + sum t;;
val sum : int list -> int = <fun>
```

If none of the patterns match the value of `expr`, the exception `Match_failure` is raised.

``` OCaml
# let unoption o =
    match o with
    | Some x -> x ;;
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
None

val unoption : 'a option -> 'a = <fun>

# let l = List.map unoption [Some 1; Some 10; None; Some 2];;
Exception: Match_failure ("expr.etex", 2, 2).
```

## Boolean operators

The expression `expr₁ && expr₂` evaluates to `true` if both `expr₁` and `expr₂` evaluate to `true`; otherwise, it evaluates to `false`. The first component, `expr₁`, is evaluated first. The second component, `expr₂`, is not evaluated if the first component evaluates to `false`. Hence, the expression `expr₁ && expr₂` behaves exactly as

`if expr₁ then expr₂ else false.`

The expression `expr₁ || expr₂` evaluates to `true` if one of the expressions `expr₁` and `expr₂` evaluates to `true`; otherwise, it evaluates to `false`. The first component, `expr₁`, is evaluated first. The second component, `expr₂`, is not evaluated if the first component evaluates to `true`. Hence, the expression `expr₁ || expr₂` behaves exactly as

`if expr₁ then true else expr₂.`

The boolean operators `&` and `or` are deprecated synonyms for (respectively) `&&` and `||`.

``` OCaml
# let xor a b =
    (a || b) && not (a && b);;
val xor : bool -> bool -> bool = <fun>
```
The only difference with the `let` construct described above is that the bindings of names to values performed by the pattern-matching are considered already performed when the expressions `expr1` to `exprn` are evaluated. That is, the expressions `expr1` to `exprn` can reference identifiers that are bound by one of the patterns `pattern1`, ..., `patternn`, and expect them to have the same value as in `expr`, the body of the `let rec` construct.

```hkl
# let rec even =
    function 0 -> true | n -> odd (n - 1)
and odd =
    function 0 -> false | n -> even (n - 1)
in
    even 1000;;
- : bool = true
```

The recursive definition is guaranteed to behave as described above if the expressions `expr1` to `exprn` are function definitions (`fun`... or `function`...), and the patterns `pattern1`...`patternn` are just value names, as in:

`let rec name1 = fun... and... and namen = fun... in expr`

This defines `name1...name_n` as mutually recursive functions local to `expr`.

The behavior of other forms of `let rec` definitions is implementation-dependent. The current implementation also supports a certain class of recursive definitions of non-functional values, as explained in section 12.1.

### 11.7.3 Local exceptions

(Introduced in OCaml 4.04)

It is possible to define local exceptions in expressions: `let exception constr-decl in expr`.

```hkl
# let map_empty_oniris f l =
    let exception Negative in
    let aux x = if x < 0 then raise Negative else f x in
    try List.map aux l with Negative -> [];
val map_empty_oniris : (int -> 'a) -> int list -> 'a list = <fun>
```

The syntactic scope of the exception constructor is the inner expression, but nothing prevents exception values created with this constructor from escaping this scope. Two executions of the definition above result in two incompatible exception constructors (as for any exception definition). For instance:

```hkl
# let gen () = let exception A in A

let () = assert(gen () = gen ());
Exception: Assert_failure ("expr.etex", 3, 9).
```

### 11.7.4 Explicit polymorphic type annotations

(Introduced in OCaml 3.12)

Polymorphic type annotations in `let`-definitions behave in a way similar to polymorphic methods:
## Loops

The expression `while expr₁ do expr₂ done` repeatedly evaluates `expr₂` while `expr₁` evaluates to `true`. The loop condition `expr₁` is evaluated and tested at the beginning of each iteration. The whole `while...done` expression evaluates to the unit value `()`.

```hql
# let chars_of_string s =
  let i = ref 0 in
  let chars = ref [] in
    while !i < String.length s do
      chars := s.[!i] :: !chars;
      i := !i + 1
    done;
    List.rev !chars;;
val chars_of_string : string -> char list = <fun>
```

The expression `for name = expr₁ to expr₂ do expr₃ done` first evaluates the expressions `expr₁` and `expr₂` (the boundaries) into integer values `n` and `p`. Then, the loop body `expr₃` is repeatedly evaluated in an environment where `name` is successively bound to the values `n`, `n + 1`, ..., `p - 1`, `p`. The loop body is never evaluated if `n > p`.

```hql
# let chars_of_string s =
  let l = ref [] in
  for p = 0 to String.length s - 1 do
    l := s.[p] :: !l
  done;
  List.rev !l;;
val chars_of_string : string -> char list = <fun>
```

The expression `for name = expr₁ downto expr₂ do expr₃ done` evaluates similarly, except that `name` is successively bound to the values `n`, `n - 1`, ..., `p + 1`, `p`. The loop body is never evaluated if `n < p`.

```hql
# let chars_of_string s =
  let l = ref [] in
  for p = String.length s - 1 downto 0 do
    l := s.[p] :: !l
  done;
  !l;;
val chars_of_string : string -> char list = <fun>
```

In both cases, the whole `for` expression evaluates to the unit value `()`.

## Exception handling

The expression

```hql
try expr
with pattern₁ -> expr₁
  | ...
  | patternₙ -> exprₙ
```
let pattern₁ : typ₁... typₙ . typexpr = expr

These annotations explicitly require the defined value to be polymorphic, and allow one to use
this polymorphism in recursive occurrences (when using `let rec`). Note however that this is a
normal polymorphic type, unifiable with any instance of itself.

### 11.7.5 Control structures

#### Sequence

The expression `expr₁ ; expr₂` evaluates `expr₁` first, then `expr₂`, and returns the value of `expr₂`.

```ocaml
# let print_pair (a, b) =
    print_string "(";
    print_string (string_of_int a);
    print_string ",";
    print_string (string_of_int b);
    print_endline ")";;
val print_pair : int * int -> unit = <fun>
```

#### Conditional

The expression `if expr₁ then expr₂ else expr₃` evaluates to the value of `expr₂` if `expr₁` evaluates to the boolean `true`, and to the value of `expr₃` if `expr₁` evaluates to the boolean `false`.

```ocaml
# let rec factorial x =
    if x <= 1 then 1 else x * factorial (x - 1);;
val factorial : int -> int = <fun>
```

The `else expr₃` part can be omitted, in which case it defaults to `else ()`.

```ocaml
# let debug = ref false

let log msg =
    if !debug then prerr_endline msg;;
val debug : bool ref = {contents = false}
val log : string -> unit = <fun>
```

#### Case expression

The expression

```haskell
match expr
  with pattern₁ -> expr₁
  | ...
  | patternₙ -> exprₙ
```

matches the value of `expr` against the patterns `pattern₁` to `patternₙ`. If the matching against `patternᵢ` succeeds, the associated expression `exprᵢ` is evaluated, and its value becomes the value of the whole `match` expression. The evaluation of `exprᵢ` takes place in an environment enriched by
evaluates the expression `expr` and returns its value if the evaluation of `expr` does not raise any exception. If the evaluation of `expr` raises an exception, the exception value is matched against the patterns `pattern₁` to `patternₙ`. If the matching against `patternᵢ` succeeds, the associated expression `exprᵢ` is evaluated, and its value becomes the value of the whole `try` expression. The evaluation of `exprᵢ` takes place in an environment enriched by the bindings performed during matching. If several patterns match the value of `expr`, the one that occurs first in the `try` expression is selected. If none of the patterns matches the value of `expr`, the exception value is raised again, thereby transparently "passing through" the `try` construct.

``` OCaml
# let find_opt p l =
    try Some (List.find p l) with Not_found -> None;;
val find_opt : ('a -> bool) -> 'a list -> 'a option = <fun>
```

## 11.7.6 Operations on data structures

### Products

The expression `expr₁, ..., exprₙ` evaluates to the `n`-tuple of the values of expressions `expr₁` to `exprₙ`. The evaluation order of the subexpressions is not specified.

``` OCaml
# (1 + 2 * 3, (1 + 2) * 3, 1 + (2 * 3));
- : int * int * int = (7, 9, 7)
```

### Variants

The expression `constr expr` evaluates to the unary variant value whose constructor is `constr`, and whose argument is the value of `expr`. Similarly, the expression `constr ( expr₁, ..., exprₙ )` evaluates to the `n`-ary variant value whose constructor is `constr` and whose arguments are the values of `expr₁, ..., exprₙ`.

The expression `constr ( expr₁, ..., exprₙ )` evaluates to the variant value whose constructor is `constr`, and whose arguments are the values of `expr₁...exprₙ`.

``` OCaml
# type t = Var of string | Not of t | And of t * t | Or of t * t

let test = And (Var "x", Not (Or (Var "y", Var "z")));
type t = Var of string | Not of t | And of t * t | Or of t * t
val test : t = And (Var "x", Not (Or (Var "y", Var "z")))
```

For lists, some syntactic sugar is provided. The expression `expr₁::expr₂` stands for the constructor (`::`) applied to the arguments (`expr₁`, `expr₂`), and therefore evaluates to the list whose head is the value of `expr₁` and whose tail is the value of `expr₂`. The expression `[expr₁; ...; exprₙ]` is equivalent to `expr₁::...:: exprₙ::[]`, and therefore evaluates to the list whose elements are the values of `expr₁` to `exprₙ`.

``` OCaml
# 0 :: [1; 2; 3] = 0 :: 1 :: 2 :: 3 :: [];
- : bool = true
```
the bindings performed during matching. If several patterns match the value of `expr`, the one that occurs first in the `match` expression is selected.

```hkl
# let rec sum l =
    match l with
    | [] -> 0
    | h :: t -> h + sum t;;
val sum : int list -> int = <fun>
```

If none of the patterns match the value of `expr`, the exception `Match_failure` is raised.

```hkl
# let unoption o =
    match o with
    | Some x -> x ;;
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched: None
```

```hkl
val unoption : 'a option -> 'a = <fun>
```

```hkl
# let l = List.map unoption [Some 1; Some 10; None; Some 2];;
Exception: Match_failure ("expr.etex", 2, 2).
```

## Boolean operators

The expression `expr₁ && expr₂` evaluates to `true` if both `expr₁` and `expr₂` evaluate to `true`; otherwise, it evaluates to `false`. The first component, `expr₁`, is evaluated first. The second component, `expr₂`, is not evaluated if the first component evaluates to `false`. Hence, the expression `expr₁ && expr₂` behaves exactly as

```hkl
if expr₁ then expr₂ else false.
```

The expression `expr₁ || expr₂` evaluates to `true` if one of the expressions `expr₁` and `expr₂` evaluates to `true`; otherwise, it evaluates to `false`. The first component, `expr₁`, is evaluated first. The second component, `expr₂`, is not evaluated if the first component evaluates to `true`. Hence, the expression `expr₁ || expr₂` behaves exactly as

```hkl
if expr₁ then true else expr₂.
```

The boolean operators `&` and `or` are deprecated synonyms for (respectively) `&&` and `||`.

```hkl
# let xor a b =
    (a || b) && not (a && b);;
val xor : bool -> bool -> bool = <fun>
```

## Loops

The expression `while expr₁ do expr₂ done` repeatedly evaluates `expr₂` while `expr₁` evaluates to `true`. The loop condition `expr₁` is evaluated and tested at the beginning of each iteration. The whole `while...done` expression evaluates to the unit value `()`.
## Polymorphic variants

The expression `tag-name expr` evaluates to the polymorphic variant value whose tag is `tag-name`, and whose argument is the value of `expr`.

```haxe
# let with_counter x = `V (x, ref 0);;
val with_counter : 'a -> [> `V of 'a * int ref ] = <fun>
```

## Records

The expression `{ field₁ [= expr₁] ; ... ; fieldₙ [= exprₙ] }` evaluates to the record value `{ field₁ = v₁; ... ; fieldₙ = vₙ }` where `vᵢ` is the value of `exprᵢ` for `i = 1, ..., n`. A single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, and a qualified identifier `module-path` . `fieldₖ` stands for `module-path` . `fieldₖ` = `fieldₖ`. The fields `field₁` to `fieldₙ` must all belong to the same record type; each field of this record type must appear exactly once in the record expression, though they can appear in any order. The order in which `expr₁` to `exprₙ` are evaluated is not specified. Optional type constraints can be added after each field `{ field₁ : typexpr₁ = expr₁ ; ... ; fieldₙ : typexprₙ = exprₙ }` to force the type of `fieldₖ` to be compatible with `typexprₖ`.

```haxe
# type t = {house_no : int; street : string; town : string; postcode : string}

let address x =
    Printf.sprintf "The occupier\n%i %s\n%s\n%s"
        x.house_no x.street x.town x.postcode;;

type t = {
    house_no : int;
    street : string;
    town : string;
    postcode : string;
}

val address : t -> string = <fun>
```

The expression `{ expr with field₁ [= expr₁] ; ... ; fieldₙ [= exprₙ] }` builds a fresh record with fields `field₁...fieldₙ` equal to `expr₁...exprₙ`, and all other fields having the same value as in the record `expr`. In other terms, it returns a shallow copy of the record `expr`, except for the fields `field₁...fieldₙ`, which are initialized to `expr₁...exprₙ`. As previously, single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, a qualified identifier `module-path` . `fieldₖ` stands for `module-path` . `fieldₖ` = `fieldₖ` and it is possible to add an optional type constraint on each field being updated with `{ expr with field₁ : typexpr₁ = expr₁ ; ... ; fieldₙ : typexprₙ = exprₙ }`.

```haxe
# type t = {house_no : int; street : string; town : string; postcode : string}

let uppercase_town address =
    {address with town = String.uppercaseocosci address.town};;

type t = {
    house_no : int;
    street : string;
    town : string;
    postcode : string;
```
``` OCaml
# let chars_of_string s =
  let i = ref 0 in
  let chars = ref [] in
  while !i < String.length s do
    chars := s.[!i] :: !chars;
    i := !i + 1
  done;
  List.rev !chars;;
val chars_of_string : string -> char list = <fun>
```

As a special case, `while true do expr done` is given a polymorphic type, allowing it to be used in place of any expression (for example as a branch of any pattern-matching).

The expression `for name = expr₁ to expr₂ do expr₃ done` first evaluates the expressions `expr₁` and `expr₂` (the boundaries) into integer values `n` and `p`. Then, the loop body `expr₃` is repeatedly evaluated in an environment where `name` is successively bound to the values `n`, `n + 1`, ..., `p - 1`, `p`. The loop body is never evaluated if `n > p`.

``` OCaml
# let chars_of_string s =
  let l = ref [] in
  for p = 0 to String.length s - 1 do
    l := s.[p] :: !l
  done;
  List.rev !l;;
val chars_of_string : string -> char list = <fun>
```

The expression `for name = expr₁ downto expr₂ do expr₃ done` evaluates similarly, except that `name` is successively bound to the values `n`, `n - 1`, ..., `p + 1`, `p`. The loop body is never evaluated if `n < p`.

``` OCaml
# let chars_of_string s =
  let l = ref [] in
  for p = String.length s - 1 downto 0 do
    l := s.[p] :: !l
  done;
  !l;;
val chars_of_string : string -> char list = <fun>
```

In both cases, the whole `for` expression evaluates to the unit value `()`.

## Exception handling

The expression

``` OCaml
try  expr
with  pattern₁ -> expr₁
    |  ...
    |  patternₙ -> exprₙ
```

evaluates the expression `expr` and returns its value if the evaluation of `expr` does not raise any exception. If the evaluation of `expr` raises an exception, the exception value is matched against the
```ocaml
}
val uppercase_town : t -> t = <fun>
```

The expression `expr_1`. `field` evaluates `expr_1` to a record value, and returns the value associated to `field` in this record value.

The expression `expr_1`. `field <- expr_2` evaluates `expr_1` to a record value, which is then modified in-place by replacing the value associated to `field` in this record by the value of `expr_2`. This operation is permitted only if `field` has been declared `mutable` in the definition of the record type. The whole expression `expr_1`. `field <- expr_2` evaluates to the unit value (`()`.

```hl
# type t = {mutable upper : int; mutable lower : int; mutable other : int}
```

```hl
let stats = {upper = 0; lower = 0; other = 0}
```

```hl
let collect =
    String.iter
    (function
      | 'A'..'Z' -> stats.upper <- stats.upper + 1
      | 'a'..'z' -> stats.lower <- stats.lower + 1
      | _ -> stats.other <- stats.other + 1);

type t = { mutable upper : int; mutable lower : int; mutable other : int; }
val stats : t = {upper = 0; lower = 0; other = 0}
val collect : string -> unit = <fun>
```

## Arrays

The expression `[| expr_1 ; ... ; expr_n |]` evaluates to a *n*-element array, whose elements are initialized with the values of `expr_1` to `expr_n` respectively. The order in which these expressions are evaluated is unspecified.

The expression `expr_1`. (`expr_2`) returns the value of element number `expr_2` in the array denoted by `expr_1`. The first element has number 0; the last element has number *n* − 1, where *n* is the size of the array. The exception `Invalid_argument` is raised if the access is out of bounds.

The expression `expr_1`. (`expr_2`) `<- expr_3` modifies in-place the array denoted by `expr_1`, replacing element number `expr_2` by the value of `expr_3`. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is (`()`.

```hl
# let scale arr n =
    for x = 0 to Array.length arr - 1 do
        arr.(x) <- arr.(x) * n
done

let x = [|1; 10; 100|]
let _ = scale x 2;;

val scale : int array -> int -> unit = <fun>
val x : int array = [|12; 20; 200|]
```
patterns `pattern₁` to `patternₙ`. If the matching against `patternᵢ` succeeds, the associated expression `exprᵢ` is evaluated, and its value becomes the value of the whole `try` expression. The evaluation of `exprᵢ` takes place in an environment enriched by the bindings performed during matching. If several patterns match the value of `expr`, the one that occurs first in the `try` expression is selected. If none of the patterns matches the value of `expr`, the exception value is raised again, thereby transparently "passing through" the `try` construct.

```hql
# let find_opt p 1 =
    try Some (List.find p 1) with Not_found -> None;;
val find_opt : ('a -> bool) -> 'a list -> 'a option = <fun>
```

## 11.7.6 Operations on data structures

### Products

The expression `expr₁, ..., exprₙ` evaluates to the *n*-tuple of the values of expressions `expr₁` to `exprₙ`. The evaluation order of the subexpressions is not specified.

```hql
# (1 + 2 * 3, (1 + 2) * 3, 1 + (2 * 3));
- : int * int * int = (7, 9, 7)
```

### Variants

The expression `constr expr` evaluates to the unary variant value whose constructor is `constr`, and whose argument is the value of `expr`. Similarly, the expression `constr ( expr₁, ..., exprₙ )` evaluates to the n-ary variant value whose constructor is `constr` and whose arguments are the values of `expr₁, ..., exprₙ`.

The expression `constr ( expr₁, ..., exprₙ )` evaluates to the variant value whose constructor is `constr`, and whose arguments are the values of `expr₁...exprₙ`.

```hql
# type t = Var of string | Not of t | And of t * t | Or of t * t
```

```hql
let test = And (Var "x", Not (Or (Var "y", Var "z")));
type t = Var of string | Not of t | And of t * t | Or of t * t
val test : t = And (Var "x", Not (Or (Var "y", Var "z")))
```

For lists, some syntactic sugar is provided. The expression `expr₁::expr₂` stands for the constructor (`::`) applied to the arguments (`expr₁`, `expr₂`), and therefore evaluates to the list whose head is the value of `expr₁` and whose tail is the value of `expr₂`. The expression `[expr₁;...; exprₙ]` is equivalent to `expr₁::...:: exprₙ::[]`, and therefore evaluates to the list whose elements are the values of `expr₁` to `exprₙ`.

```hql
# 0 :: [1; 2; 3] = 0 :: 1 :: 2 :: 3 :: [];
- : bool = true
```

### Polymorphic variants

The expression `tag-name expr` evaluates to the polymorphic variant value whose tag is `tag-name`, and whose argument is the value of `expr`.
## Strings

The expression `expr1.[expr2]` returns the value of character number `expr2` in the string denoted by `expr1`. The first character has number 0; the last character has number `n-1`, where `n` is the length of the string. The exception `Invalid_argument` is raised if the access is out of bounds.

```pascal
# let iter f s =
    for x = 0 to String.length s - 1 do f s.[x] done;;
val iter : (char -> 'a) -> string -> unit = <fun>
```

The expression `expr1.[expr2] <- expr3` modifies in-place the string denoted by `expr1`, replacing character number `expr2` by the value of `expr3`. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is `()`. **Note:** this possibility is offered only for backward compatibility with older versions of OCaml and will be removed in a future version. New code should use byte sequences and the `Bytes.set` function.

## 11.7.7 Operators

Symbols from the class `infix-symbol`, as well as the keywords `*`, `+`, `-`, `-.`, `=`, `!=`, `<>`, `or`, `||`, `&`, `&&`, `:=`, `mod`, `land`, `lor`, `lxor`, `lsl`, `lsr`, and `asr` can appear in infix position (between two expressions). Symbols from the class `prefix-symbol`, as well as the keywords `-` and `-`. can appear in prefix position (in front of an expression).

```pascal
# (( * ), ( := ), ( || ));;
- : (int -> int -> int) * ('a ref -> 'a -> unit) * (bool -> bool -> bool) =
  (<fun>, <fun>, <fun>)
```

Infix and prefix symbols do not have a fixed meaning: they are simply interpreted as applications of functions bound to the names corresponding to the symbols. The expression `prefix-symbol expr` is interpreted as the application `( prefix-symbol ) expr`. Similarly, the expression `expr1 infix-symbol expr2` is interpreted as the application `( infix-symbol ) expr1 expr2`.

The table below lists the symbols defined in the initial environment and their initial meaning. (See the description of the core library module `Stdlib` in chapter 27 for more details). Their meaning may be changed at any time using `let (infix-op) name1 name2 = ...`

```pascal
# let ( + ), ( - ), ( * ), ( / ) = Int64.(add, sub, mul, div);;
val ( + ) : int64 -> int64 -> int64 = <fun>
val ( - ) : int64 -> int64 -> int64 = <fun>
val ( * ) : int64 -> int64 -> int64 = <fun>
val ( / ) : int64 -> int64 -> int64 = <fun>
```

**Note:** the operators `&&`, `||`, and `~-` are handled specially and it is not advisable to change their meaning.

The keywords `-` and `-`. can appear both as infix and prefix operators. When they appear as prefix operators, they are interpreted respectively as the functions (`~-`) and (`~-.`).
```ocaml
# let with_counter x = `V (x, ref 0);;
val with_counter : 'a -> [> `V of 'a * int ref ] = <fun>
```

## Records

The expression `{ field₁ [= expr₁] ; ... ; fieldₙ [= exprₙ] }` evaluates to the record value `{ field₁ = v₁; ... ; fieldₙ = vₙ }` where `vᵢ` is the value of `exprᵢ` for `i = 1, ..., n`. A single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, and a qualified identifier `module-path` . `fieldₖ` stands for `module-path` . `fieldₖ` = `fieldₖ`. The fields `field₁` to `fieldₙ` must all belong to the same record type; each field of this record type must appear exactly once in the record expression, though they can appear in any order. The order in which `expr₁` to `exprₙ` are evaluated is not specified. Optional type constraints can be added after each field `{ field₁ : typexpr₁ = expr₁ ; ... ; fieldₙ : typexprₙ = exprₙ }` to force the type of `fieldₖ` to be compatible with `typexprₖ`.

```ocaml
# type t = {house_no : int; street : string; town : string; postcode : string}

let address x =
    Printf.sprintf "The occupier\n%i %s\n%s\n%s"
        x.house_no x.street x.town x.postcode;;

type t = {
    house_no : int;
    street : string;
    town : string;
    postcode : string;
}

val address : t -> string = <fun>
```

The expression `{ expr with field₁ [= expr₁] ; ... ; fieldₙ [= exprₙ] }` builds a fresh record with fields `field₁...fieldₙ` equal to `expr₁...exprₙ`, and all other fields having the same value as in the record `expr`. In other terms, it returns a shallow copy of the record `expr`, except for the fields `field₁...fieldₙ`, which are initialized to `expr₁...exprₙ`. As previously, single identifier `fieldₖ` stands for `fieldₖ = fieldₖ`, a qualified identifier `module-path` . `fieldₖ` stands for `module-path` . `fieldₖ` = `fieldₖ` and it is possible to add an optional type constraint on each field being updated with `{ expr with field₁ : typexpr₁ = expr₁ ; ... ; fieldₙ : typexprₙ = exprₙ }`.

```ocaml
# type t = {house_no : int; street : string; town : string; postcode : string}

let uppercase_town address =
    {address with town = String.uppercaseocosci address.town};;

type t = {
    house_no : int;
    street : string;
    town : string;
    postcode : string;
}

val uppercase_town : t -> t = <fun>
```

The expression `expr₁ . field` evaluates `expr₁` to a record value, and returns the value associated to `field` in this record value.
<table><thead><tr><th>Operator</th><th>Initial meaning</th></tr></thead><tbody><tr><td>+</td><td>Integer addition.</td></tr><tr><td>- (infix)</td><td>Integer subtraction.</td></tr><tr><td>~ - (prefix)</td><td>Integer negation.</td></tr><tr><td>*</td><td>Integer multiplication.</td></tr><tr><td>/</td><td>Integer division. Raise Division_by_zero if second argument is zero.</td></tr><tr><td>mod</td><td>Integer modulus. Raise Division_by_zero if second argument is zero.</td></tr><tr><td>land</td><td>Bitwise logical "and" on integers.</td></tr><tr><td>lor</td><td>Bitwise logical "or" on integers.</td></tr><tr><td>lxor</td><td>Bitwise logical "exclusive or" on integers.</td></tr><tr><td>lsl</td><td>Bitwise logical shift left on integers.</td></tr><tr><td>lsr</td><td>Bitwise logical shift right on integers.</td></tr><tr><td>asr</td><td>Bitwise arithmetic shift right on integers.</td></tr><tr><td>+.</td><td>Floating-point addition.</td></tr><tr><td>-. (infix)</td><td>Floating-point subtraction.</td></tr><tr><td>~-. - (prefix)</td><td>Floating-point negation.</td></tr><tr><td>.*</td><td>Floating-point multiplication.</td></tr><tr><td>/.</td><td>Floating-point division.</td></tr><tr><td>**</td><td>Floating-point exponentiation.</td></tr><tr><td>@</td><td>List concatenation.</td></tr><tr><td>~</td><td>String concatenation.</td></tr><tr><td>!</td><td>Dereferencing (return the current contents of a reference).</td></tr><tr><td>:=</td><td>Reference assignment (update the reference given as first argument with the value of the second argument).</td></tr><tr><td>=</td><td>Structural equality test.</td></tr><tr><td>&gt;&gt;</td><td>Structural inequality test.</td></tr><tr><td>==</td><td>Physical equality test.</td></tr><tr><td>!=</td><td>Physical inequality test.</td></tr><tr><td>&lt;</td><td>Test "less than".</td></tr><tr><td>&lt;=</td><td>Test "less than or equal".</td></tr><tr><td>&gt;</td><td>Test "greater than".</td></tr><tr><td>&gt;=</td><td>Test "greater than or equal".</td></tr><tr><td>&amp;&amp; &amp;</td><td>Boolean conjunction.</td></tr><tr><td>|| or</td><td>Boolean disjunction.</td></tr></tbody></table>

### 11.7.8 Objects

#### Object creation

When `class-path` evaluates to a class body, `new class-path` evaluates to a new object containing the instance variables and methods of this class.

``` OCaml
# class of_list (lst : int list) = object
    val mutable l = lst
    method next =
        match l with
```
The expression `expr_1`. `field` `<- expr_2` evaluates `expr_1` to a record value, which is then modified in-place by replacing the value associated to `field` in this record by the value of `expr_2`. This operation is permitted only if `field` has been declared *mutable* in the definition of the record type. The whole expression `expr_1`. `field` `<- expr_2` evaluates to the unit value (`=`).

```h
# type t = {mutable upper : int; mutable lower : int; mutable other : int}
```

```h
let stats = {upper = 0; lower = 0; other = 0}
```

```h
let collect =
```

```h
    String.iter
```

```h
    (function
```

```h
        | 'A'..'Z' -> stats.upper <- stats.upper + 1
```

```h
        | 'a'..'z' -> stats.lower <- stats.lower + 1
```

```h
        | _ -> stats.other <- stats.other + 1);
```

```h
type t = { mutable upper : int; mutable lower : int; mutable other : int; }
```

```h
val stats : t = {upper = 0; lower = 0; other = 0}
```

```h
val collect : string -> unit = <fun>
```

## Arrays

The expression `[| expr_1 ; ... ; expr_n |]` evaluates to a *n*-element array, whose elements are initialized with the values of `expr_1` to `expr_n` respectively. The order in which these expressions are evaluated is unspecified.

The expression `expr_1`. (`expr_2` ) returns the value of element number `expr_2` in the array denoted by `expr_1`. The first element has number 0; the last element has number *n* − 1, where *n* is the size of the array. The exception `Invalid_argument` is raised if the access is out of bounds.

The expression `expr_1`. (`expr_2` ) `<- expr_3` modifies in-place the array denoted by `expr_1`, replacing element number `expr_2` by the value of `expr_3`. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is (`=`).

```h
# let scale arr n =
    for x = 0 to Array.length arr - 1 do
        arr.(x) <- arr.(x) * n
    done
```

```h
let x = [|1; 10; 100|]
let _ = scale x 2;
```

```h
val scale : int array -> int -> unit = <fun>
```

```h
val x : int array = [|2; 20; 200|]
```

## Strings

The expression `expr_1`. `[ expr_2 ]` returns the value of character number `expr_2` in the string denoted by `expr_1`. The first character has number 0; the last character has number *n* − 1, where *n* is the length of the string. The exception `Invalid_argument` is raised if the access is out of bounds.
```kotlin
    [] -> raise (Failure "empty list");
    h::t -> l <- t; h
end
```

```kotlin
let a = new of_list [1; 1; 2; 3; 5; 8; 13]
```

```kotlin
let b = new of_list;;
```

```kotlin
class of_list :
    int list -> object val mutable l : int list method next : int end
val a : of_list = <obj>
val b : int list -> of_list = <fun>
```

When `class-path` evaluates to a class function, `new class-path` evaluates to a function expecting the same number of arguments and returning a new object of this class.

## Immediate object creation

Creating directly an object through the `object class-body end` construct is operationally equivalent to defining locally a `class class-name = object class-body end` —see sections 11.9.2 and following for the syntax of `class-body`— and immediately creating a single object from it by `new class-name`.

```kotlin
# let o =
    object
        val secret = 99
        val password = "unlock"
        method get guess = if guess <> password then None else Some secret
end;;

val o : < get : string -> int option > = <obj>
```

The typing of immediate objects is slightly different from explicitly defining a class in two respects. First, the inferred object type may contain free type variables. Second, since the class body of an immediate object will never be extended, its self type can be unified with a closed object type.

## Method invocation

The expression `expr # method-name` invokes the method `method-name` of the object denoted by `expr`.

```kotlin
# class of_list (lst : int list) = object
    val mutable l = lst
    method next =
        match l with
        | [] -> raise (Failure "empty list");
        | h::t -> l <- t; h
end
```

```kotlin
let a = new of_list [1; 1; 2; 3; 5; 8; 13]
```
``` OCaml
# let iter f s =
    for x = 0 to String.length s - 1 do f s.[x] done;;
val iter : (char -> 'a) -> string -> unit = <fun>
```

The expression `expr₁ . [ expr₂ ] <- expr₃` modifies in-place the string denoted by `expr₁`, replacing character number `expr₂` by the value of `expr₃`. The exception `Invalid_argument` is raised if the access is out of bounds. The value of the whole expression is `()`. **Note:** this possibility is offered only for backward compatibility with older versions of OCaml and will be removed in a future version. New code should use byte sequences and the `Bytes.set` function.

### 11.7.7 Operators

Symbols from the class `infix-symbol`, as well as the keywords `*`, `+`, `-`, `-.`, `=`, `!=`, `<>`, `or`, `||`, `&`, `&&`, `:=`, `mod`, `land`, `lor`, `lxor`, `lsl`, `lsr`, and `asr` can appear in infix position (between two expressions). Symbols from the class `prefix-symbol`, as well as the keywords `-` and `-`. can appear in prefix position (in front of an expression).

``` OCaml
# (( * ), ( := ), ( || ));;
- : (int -> int -> int) * ('a ref -> 'a -> unit) * (bool -> bool -> bool) =
  (<fun>, <fun>, <fun>)
```

Infix and prefix symbols do not have a fixed meaning: they are simply interpreted as applications of functions bound to the names corresponding to the symbols. The expression `prefix-symbol expr` is interpreted as the application `( prefix-symbol ) expr`. Similarly, the expression `expr₁ infix-symbol expr₂` is interpreted as the application `( infix-symbol ) expr₁ expr₂`.

The table below lists the symbols defined in the initial environment and their initial meaning. (See the description of the core library module `Stdlib` in chapter 28 for more details). Their meaning may be changed at any time using `let ( infix-op ) name₁ name₂ = ...`

``` OCaml
# let ( + ), ( - ), ( * ), ( / ) = Int64.(add, sub, mul, div);;
val ( + ) : int64 -> int64 -> int64 = <fun>
val ( - ) : int64 -> int64 -> int64 = <fun>
val ( * ) : int64 -> int64 -> int64 = <fun>
val ( / ) : int64 -> int64 -> int64 = <fun>
```

**Note:** the operators `&&`, `||`, and `~-` are handled specially and it is not advisable to change their meaning.

The keywords `-` and `-`. can appear both as infix and prefix operators. When they appear as prefix operators, they are interpreted respectively as the functions (`~-`) and (`~-.`).
``` OCaml
let third = ignore a#next; ignore a#next; a#next;;
class of_list :
    int list -> object val mutable l : int list method next : int end
val a : of_list = <obj>
val third : int = 2
```

If *method-name* is a polymorphic method, its type should be known at the invocation site. This is true for instance if *expr* is the name of a fresh object (*let ident = new class-path ...*) or if there is a type constraint. Principality of the derivation can be checked in the `-principal` mode.

## Accessing and modifying instance variables

The instance variables of a class are visible only in the body of the methods defined in the same class or a class that inherits from the class defining the instance variables. The expression *inst-var-name* evaluates to the value of the given instance variable. The expression *inst-var-name* <- *expr* assigns the value of *expr* to the instance variable *inst-var-name*, which must be mutable. The whole expression *inst-var-name* <- *expr* evaluates to ().

``` OCaml
# class of_list (lst : int list) = object
    val mutable l = lst
    method next =
        match l with
        | [] -> raise (Failure "empty list");
        | h::t -> l <- t; h
        end;;
class of_list :
    int list -> object val mutable l : int list method next : int end
```

## Object duplication

An object can be duplicated using the library function `Oo.copy` (see module `Oo` [28.38]). Inside a method, the expression `{< [inst-var-name [= expr] {; inst-var-name [= expr]} >}` returns a copy of self with the given instance variables replaced by the values of the associated expressions. A single instance variable name *id* stands for *id = id*. Other instance variables have the same value in the returned object as in self.

``` OCaml
# let o =
object
    val secret = 99
    val password = "unlock"
    method get guess = if guess <> password then None else Some secret
    method with_new_secret s = {< secret = s >}
end;;
val o : < get : string -> int option; with_new_secret : int -> 'a > as 'a =
<obj>
```
<table><thead><tr><th>Operator</th><th>Initial meaning</th></tr></thead><tbody><tr><td>+</td><td>Integer addition.</td></tr><tr><td>- (infix)</td><td>Integer subtraction.</td></tr><tr><td>~ - (prefix)</td><td>Integer negation.</td></tr><tr><td>*</td><td>Integer multiplication.</td></tr><tr><td>/</td><td>Integer division. Raise Division_by_zero if second argument is zero.</td></tr><tr><td>mod</td><td>Integer modulus. Raise Division_by_zero if second argument is zero.</td></tr><tr><td>land</td><td>Bitwise logical "and" on integers.</td></tr><tr><td>lor</td><td>Bitwise logical "or" on integers.</td></tr><tr><td>lxor</td><td>Bitwise logical "exclusive or" on integers.</td></tr><tr><td>lsl</td><td>Bitwise logical shift left on integers.</td></tr><tr><td>lsr</td><td>Bitwise logical shift right on integers.</td></tr><tr><td>asr</td><td>Bitwise arithmetic shift right on integers.</td></tr><tr><td>+.</td><td>Floating-point addition.</td></tr><tr><td>-. (infix)</td><td>Floating-point subtraction.</td></tr><tr><td>~-. - (prefix)</td><td>Floating-point negation.</td></tr><tr><td>.*</td><td>Floating-point multiplication.</td></tr><tr><td>/.</td><td>Floating-point division.</td></tr><tr><td>**</td><td>Floating-point exponentiation.</td></tr><tr><td>@</td><td>List concatenation.</td></tr><tr><td>~</td><td>String concatenation.</td></tr><tr><td>!</td><td>Dereferencing (return the current contents of a reference).</td></tr><tr><td>:=</td><td>Reference assignment (update the reference given as first argument with the value of the second argument).</td></tr><tr><td>=</td><td>Structural equality test.</td></tr><tr><td>&gt;&gt;</td><td>Structural inequality test.</td></tr><tr><td>==</td><td>Physical equality test.</td></tr><tr><td>!=</td><td>Physical inequality test.</td></tr><tr><td>&lt;</td><td>Test "less than".</td></tr><tr><td>&lt;=</td><td>Test "less than or equal".</td></tr><tr><td>&gt;</td><td>Test "greater than".</td></tr><tr><td>&gt;=</td><td>Test "greater than or equal".</td></tr><tr><td>&amp;&amp; &amp;</td><td>Boolean conjunction.</td></tr><tr><td>|| or</td><td>Boolean disjunction.</td></tr></tbody></table>

### 11.7.8 Objects

#### Object creation

When `class-path` evaluates to a class body, `new class-path` evaluates to a new object containing the instance variables and methods of this class.

```python
# class of_list (lst : int list) = object
    val mutable l = lst
    method next =
        match l with
```
### 11.7.9 Coercions

Expressions whose type contains object or polymorphic variant types can be explicitly coerced (weakened) to a supertype. The expression (`expr` :> `typexpr`) coerces the expression `expr` to type `typexpr`. The expression (`expr` : `typexpr<sub>1</sub>` :> `typexpr<sub>2</sub>`) coerces the expression `expr` from type `typexpr<sub>1</sub>` to type `typexpr<sub>2</sub>`.

The former operator will sometimes fail to coerce an expression `expr` from a type `typ<sub>1</sub>` to a type `typ<sub>2</sub>` even if type `typ<sub>1</sub>` is a subtype of type `typ<sub>2</sub>`: in the current implementation it only expands two levels of type abbreviations containing objects and/or polymorphic variants, keeping only recursion when it is explicit in the class type (for objects). As an exception to the above algorithm, if both the inferred type of `expr` and `typ` are ground (i.e. do not contain type variables), the former operator behaves as the latter one, taking the inferred type of `expr` as `typ<sub>1</sub>`. In case of failure with the former operator, the latter one should be used.

It is only possible to coerce an expression `expr` from type `typ<sub>1</sub>` to type `typ<sub>2</sub>`, if the type of `expr` is an instance of `typ<sub>1</sub>` (like for a type annotation), and `typ<sub>1</sub>` is a subtype of `typ<sub>2</sub>`. The type of the coerced expression is an instance of `typ<sub>2</sub>`. If the types contain variables, they may be instantiated by the subtyping algorithm, but this is only done after determining whether `typ<sub>1</sub>` is a potential subtype of `typ<sub>2</sub>`. This means that typing may fail during this latter unification step, even if some instance of `typ<sub>1</sub>` is a subtype of some instance of `typ<sub>2</sub>`. In the following paragraphs we describe the subtyping relation used.

#### Object types

A fixed object type admits as subtype any object type that includes all its methods. The types of the methods shall be subtypes of those in the supertype. Namely,

`< met<sub>1</sub> : typ<sub>1</sub> ; ... ; met<sub>n</sub> : typ<sub>n</sub> >`

is a supertype of

`< met<sub>1</sub> : typ'<sub>1</sub> ; ... ; met<sub>n</sub> : typ'<sub>n</sub> ; met<sub>n+1</sub> : typ'<sub>n+1</sub> ; ... ; met<sub>n+m</sub> : typ'<sub>n+m</sub> [ ; ... ] >`

which may contain an ellipsis `..` if every `typ<sub>i</sub>` is a supertype of the corresponding `typ'<sub>i</sub>`.

A monomorphic method type can be a supertype of a polymorphic method type. Namely, if `typ` is an instance of `typ'`, then `'a<sub>1</sub>... 'a<sub>n</sub> . typ'` is a subtype of `typ`.

Inside a class definition, newly defined types are not available for subtyping, as the type abbreviations are not yet completely defined. There is an exception for coercing `self` to the (exact) type of its class: this is allowed if the type of `self` does not appear in a contravariant position in the class type, i.e. if there are no binary methods.

#### Polymorphic variant types

A polymorphic variant type `typ` is a subtype of another polymorphic variant type `typ'` if the upper bound of `typ` (i.e. the maximum set of constructors that may appear in an instance of `typ`) is included in the lower bound of `typ'`, and the types of arguments for the constructors of `typ` are subtypes of those in `typ'`. Namely,

`[ < ] ` `C<sub>1</sub> of typ<sub>1</sub> | ... | ` `C<sub>n</sub> of typ<sub>n</sub> ]`
```ocaml
| [] -> raise (Failure "empty list");
| h::t -> l <- t; h
end

let a = new of_list [1; 1; 2; 3; 5; 8; 13]

let b = new of_list;;

class of_list :
  int list -> object val mutable l : int list method next : int end
val a : of_list = <obj>
val b : int list -> of_list = <fun>
```

When `class-path` evaluates to a class function, `new class-path` evaluates to a function expecting the same number of arguments and returning a new object of this class.

## Immediate object creation

Creating directly an object through the `object class-body end` construct is operationally equivalent to defining locally a `class class-name = object class-body end` —see sections 11.9.2 and following for the syntax of `class-body`— and immediately creating a single object from it by `new class-name`.

```ocaml
# let o =
object
  val secret = 99
  val password = "unlock"
  method get guess = if guess <> password then None else Some secret
end;;

val o : < get : string -> int option > = <obj>
```

The typing of immediate objects is slightly different from explicitly defining a class in two respects. First, the inferred object type may contain free type variables. Second, since the class body of an immediate object will never be extended, its self type can be unified with a closed object type.

## Method invocation

The expression `expr # method-name` invokes the method `method-name` of the object denoted by `expr`.

```ocaml
# class of_list (lst : int list) = object
  val mutable l = lst
  method next =
    match l with
    | [] -> raise (Failure "empty list");
    | h::t -> l <- t; h
end

let a = new of_list [1; 1; 2; 3; 5; 8; 13]
```
which may be a shrinkable type, is a subtype of

[[> `C1` of `typ'₁` | ... | `Cn` of `typ'ₙ` | `Cn+1` of `typ'_{n+1}` | ... | `Cn+m` of `typ'_{n+m}`]]

which may be an extensible type, if every `typᵢ` is a subtype of `typ'ᵢ`.

## Variance

Other types do not introduce new subtyping, but they may propagate the subtyping of their arguments. For instance, `typ₁ * typ₂` is a subtype of `typ'₁ * typ'₂` when `typ₁` and `typ₂` are respectively subtypes of `typ'₁` and `typ'₂`. For function types, the relation is more subtle: `typ₁ -> typ₂` is a subtype of `typ'₁ -> typ'₂` if `typ₁` is a supertype of `typ'₁` and `typ₂` is a subtype of `typ'₂`. For this reason, function types are covariant in their second argument (like tuples), but contravariant in their first argument. Mutable types, like `array` or `ref` are neither covariant nor contravariant, they are nonvariant, that is they do not propagate subtyping.

For user-defined types, the variance is automatically inferred: a parameter is covariant if it has only covariant occurrences, contravariant if it has only contravariant occurrences, variance-free if it has no occurrences, and nonvariant otherwise. A variance-free parameter may change freely through subtyping, it does not have to be a subtype or a supertype. For abstract and private types, the variance must be given explicitly (see section 11.8.1), otherwise the default is nonvariant. This is also the case for constrained arguments in type definitions.

## 11.7.10 Other

### Assertion checking

OCaml supports the `assert` construct to check debugging assertions. The expression `assert expr` evaluates the expression `expr` and returns `()` if `expr` evaluates to `true`. If it evaluates to `false` the exception `Assert_failure` is raised with the source file name and the location of `expr` as arguments. Assertion checking can be turned off with the `-noassert` compiler option. In this case, `expr` is not evaluated at all.

```ocaml
# let f a b c =
    assert (a <= b && b <= c);
    (b -. a) / (c -. b);;
val f : float -> float -> float -> float = <fun>
```

As a special case, `assert` is reduced to `raise (Assert_failure ... )`, which gives it a polymorphic type. This means that it can be used in place of any expression (for example as a branch of any pattern-matching). It also means that the `assert` "assertions" cannot be turned off by the `-noassert` option.

```ocaml
# let min Known_nonempty = function
  | [] -> assert false
  | 1 -> List.hd (List.sort compare 1);;
val min Known_nonempty : 'a list -> 'a = <fun>
```
```kotlin
let third = ignore a#next; ignore a#next; a#next;;
class of_list :
    int list -> object val mutable 1 : int list method next : int end
val a : of_list = <obj>
val third : int = 2
```

If `method-name` is a polymorphic method, its type should be known at the invocation site. This is true for instance if `expr` is the name of a fresh object (`let ident = new class-path ...`) or if there is a type constraint. Principality of the derivation can be checked in the `-principal` mode.

## Accessing and modifying instance variables

The instance variables of a class are visible only in the body of the methods defined in the same class or a class that inherits from the class defining the instance variables. The expression `inst-var-name` evaluates to the value of the given instance variable. The expression `inst-var-name <- expr` assigns the value of `expr` to the instance variable `inst-var-name`, which must be mutable. The whole expression `inst-var-name <- expr` evaluates to `()`.

```kotlin
# class of_list (lst : int list) = object
    val mutable 1 = lst
    method next =
        match 1 with
            | [] -> raise (Failure "empty list");
            | h::t -> l <- t; h
                (* access instance variable *)
            end;;
class of_list :
    int list -> object val mutable 1 : int list method next : int end
```

## Object duplication

An object can be duplicated using the library function `Oo.copy` (see module `Oo` [29.40]). Inside a method, the expression `{< [inst-var-name [= expr] {; inst-var-name [= expr]} } >}` returns a copy of self with the given instance variables replaced by the values of the associated expressions. A single instance variable name `id` stands for `id = id`. Other instance variables have the same value in the returned object as in self.

```kotlin
# let o =
    object
        val secret = 99
        val password = "unlock"
        method get guess = if guess <> password then None else Some secret
        method with_new_secret s = {< secret = s >}
end;;

val o : < get : string -> int option; with_new_secret : int -> 'a > as 'a =
    <obj>
```
## Lazy expressions

The expression `lazy expr` returns a value `v` of type `Lazy.t` that encapsulates the computation of `expr`. The argument `expr` is not evaluated at this point in the program. Instead, its evaluation will be performed the first time the function `Lazy.force` is applied to the value `v`, returning the actual value of `expr`. Subsequent applications of `Lazy.force` to `v` do not evaluate `expr` again. Applications of `Lazy.force` may be implicit through pattern matching (see 11.6.1).

```hkl
# let lazy_greeter = lazy (print_string "Hello, World!\n");
val lazy_greeter : unit lazy_t = <lazy>
```

```hkl
# Lazy.force lazy_greeter;,
Hello, World!
- : unit = ()
```

## Local modules

The expression `let module module-name = module-expr in expr` locally binds the module expression `module-expr` to the identifier `module-name` during the evaluation of the expression `expr`. It then returns the value of `expr`. For example:

```hkl
# let remove_duplicates comparison Fun string_list =
let module StringSet =
  Set.Make(struct type t = string
    let compare = comparison Fun end)
in
  StringSet
  (List.fold_right StringSet.add string_list StringSet.empty);,
val remove_duplicates :
  (string -> string -> int) -> string list -> string list = <fun>
```

## Local opens

The expressions `let open module-path in expr` and `module-path` (`expr`) are strictly equivalent. These constructions locally open the module referred to by the module path `module-path` in the respective scope of the expression `expr`.

```hkl
# let map_3d_matrix f m =
let open Array in
  map (map (map f)) m

let map_3d_matrix' f =
  Array.(map (map (map f)));,
val map_3d_matrix :
  ('a -> 'b) -> 'a array array array -> 'b array array array = <fun>
val map_3d_matrix' :
  ('a -> 'b) -> 'a array array array -> 'b array array array = <fun>
```
### 11.7.9 Coercions

Expressions whose type contains object or polymorphic variant types can be explicitly coerced (weakened) to a supertype. The expression `( expr :> typexpr )` coerces the expression `expr` to type `typexpr`. The expression `( expr : typexpr₁ :> typexpr₂ )` coerces the expression `expr` from type `typexpr₁` to type `typexpr₂`.

The former operator will sometimes fail to coerce an expression `expr` from a type `typ₁` to a type `typ₂` even if type `typ₁` is a subtype of type `typ₂`: in the current implementation it only expands two levels of type abbreviations containing objects and/or polymorphic variants, keeping only recursion when it is explicit in the class type (for objects). As an exception to the above algorithm, if both the inferred type of `expr` and `typ` are ground (i.e. do not contain type variables), the former operator behaves as the latter one, taking the inferred type of `expr` as `typ₁`. In case of failure with the former operator, the latter one should be used.

It is only possible to coerce an expression `expr` from type `typ₁` to type `typ₂`, if the type of `expr` is an instance of `typ₁` (like for a type annotation), and `typ₁` is a subtype of `typ₂`. The type of the coerced expression is an instance of `typ₂`. If the types contain variables, they may be instantiated by the subtyping algorithm, but this is only done after determining whether `typ₁` is a potential subtype of `typ₂`. This means that typing may fail during this latter unification step, even if some instance of `typ₁` is a subtype of some instance of `typ₂`. In the following paragraphs we describe the subtyping relation used.

#### Object types

A fixed object type admits as subtype any object type that includes all its methods. The types of the methods shall be subtypes of those in the supertype. Namely,

`< met₁ : typ₁ ; ... ; metₙ : typₙ >`

is a supertype of

`< met₁ : typ'₁ ; ... ; metₙ : typ'ₙ ; metₙ₊₁ : typ'ₙ₊₁ ; ... ; metₙ₊ₘ : typ'ₙ₊ₘ [ ; ... ] >`

which may contain an ellipsis `..` if every `typᵢ` is a supertype of the corresponding `typ'ᵢ`.

A monomorphic method type can be a supertype of a polymorphic method type. Namely, if `typ` is an instance of `typ'`, then `'a₁... 'aₙ . typ'` is a subtype of `typ`.

Inside a class definition, newly defined types are not available for subtyping, as the type abbreviations are not yet completely defined. There is an exception for coercing `self` to the (exact) type of its class: this is allowed if the type of `self` does not appear in a contravariant position in the class type, i.e. if there are no binary methods.

#### Polymorphic variant types

A polymorphic variant type `typ` is a subtype of another polymorphic variant type `typ'` if the upper bound of `typ` (i.e. the maximum set of constructors that may appear in an instance of `typ`) is included in the lower bound of `typ'`, and the types of arguments for the constructors of `typ` are subtypes of those in `typ'`. Namely,

`[ [<] ` `C₁` of typ₁ | ... | ` `Cₙ` of typₙ ]`
When the body of a local open expression is delimited by `[]`, `| |`, or `{ }`, the parentheses can be omitted. For expression, parentheses can also be omitted for `{ < > }`. For example, `module-path . [ expr ]` is equivalent to `module-path . ([ expr ])`, and `module-path . [ | expr | ]` is equivalent to `module-path . ([ | expr |])`.

```ocaml
# let vector = Random.[|int 255; int 255; int 255; int 255|];
val vector : int array = [|220; 90; 247; 144|]
```

## 11.8 Type and exception definitions

### 11.8.1 Type definitions

Type definitions bind type constructors to data types: either variant types, record types, type abbreviations, or abstract data types. They also bind the value constructors and record fields associated with the definition.

```
type-definition ::= type [nonrec] typedef {and typedef}

typedef ::= [type-params] typeconstr-name type-information

type-information ::= [type-equation] [type-representation] {type-constraint}

type-equation ::= = typexpr

type-representation ::= = [|] constr-decl {| constr-decl}
                       | = record-decl
                       | = |

type-params ::= type-param
               | ( type-param {, type-param} )

type-param ::= [ext-variance] ' ident

ext-variance ::= variance [injectivity]
               | injectivity [variance]

variance ::= +
             | -

injectivity ::= !

record-decl ::= { field-decl {; field-decl} [;] }

constr-decl ::= (constr-name | [] | (:*)) [of constr-args]

constr-args ::= typexpr {* typexpr}

field-decl ::= [mutable] field-name : poly-typexpr

type-constraint ::= constraint typexpr = typexpr
```

See also the following language extensions: private types, generalized algebraic datatypes, attributes, extension nodes, extensible variant types and inline records.
which may be a shrinkable type, is a subtype of

[[> `C₁` of `typ'₁` | ... | `Cₙ` of `typ'ₙ` | `Cₙ₊₁` of `typ'ₙ₊₁` | ... | `Cₙ₊ₘ` of `typ'ₙ₊ₘ`]]

which may be an extensible type, if every `typᵢ` is a subtype of `typ'ᵢ`.

## Variance

Other types do not introduce new subtyping, but they may propagate the subtyping of their arguments. For instance, `typ₁ * typ₂` is a subtype of `typ'₁ * typ'₂` when `typ₁` and `typ₂` are respectively subtypes of `typ'₁` and `typ'₂`. For function types, the relation is more subtle: `typ₁ -> typ₂` is a subtype of `typ'₁ -> typ'₂` if `typ₁` is a supertype of `typ'₁` and `typ₂` is a subtype of `typ'₂`. For this reason, function types are covariant in their second argument (like tuples), but contravariant in their first argument. Mutable types, like `array` or `ref` are neither covariant nor contravariant, they are nonvariant, that is they do not propagate subtyping.

For user-defined types, the variance is automatically inferred: a parameter is covariant if it has only covariant occurrences, contravariant if it has only contravariant occurrences, variance-free if it has no occurrences, and nonvariant otherwise. A variance-free parameter may change freely through subtyping, it does not have to be a subtype or a supertype. For abstract and private types, the variance must be given explicitly (see section 11.8.1), otherwise the default is nonvariant. This is also the case for constrained arguments in type definitions.

## 11.7.10 Other

### Assertion checking

OCaml supports the `assert` construct to check debugging assertions. The expression `assert expr` evaluates the expression `expr` and returns `()` if `expr` evaluates to `true`. If it evaluates to `false` the exception `Assert_failure` is raised with the source file name and the location of `expr` as arguments. Assertion checking can be turned off with the `-noassert` compiler option. In this case, `expr` is not evaluated at all.

```ocaml
# let f a b c =
    assert (a <= b && b <= c);
    (b -. a) / (c -. b);;
val f : float -> float -> float -> float = <fun>
```

As a special case, `assert false` is reduced to `raise (Assert_failure ... )`, which gives it a polymorphic type. This means that it can be used in place of any expression (for example as a branch of any pattern-matching). It also means that the `assert false` "assertions" cannot be turned off by the `-noassert` option.

```ocaml
# let min Known_nonempty = function
  | [] -> assert false
  | 1 -> List.hd (List.sort compare 1);;
val min Known_nonempty : 'a list -> 'a = <fun>
```
Type definitions are introduced by the `type` keyword, and consist in one or several simple definitions, possibly mutually recursive, separated by the `and` keyword. Each simple definition defines one type constructor.

A simple definition consists in a lowercase identifier, possibly preceded by one or several type parameters, and followed by an optional type equation, then an optional type representation, and then a constraint clause. The identifier is the name of the type constructor being defined.

```h
type colour =
  | Red   | Green | Blue | Yellow | Black | White
  | RGB of {r : int; g : int; b : int}
```

```h
type 'a tree = Lf | Br of 'a * 'a tree * 'a;;
```

```h
type t = {decoration : string; substance : t'}
and t' = Int of int | List of t list
```

In the right-hand side of type definitions, references to one of the type constructor name being defined are considered as recursive, unless `type` is followed by `nonrec`. The `nonrec` keyword was introduced in OCaml 4.02.2.

The optional type parameters are either one type variable `'ident'`, for type constructors with one parameter, or a list of type variables (`'ident₁, ..., 'identₙ`), for type constructors with several parameters. Each type parameter may be prefixed by a variance constraint `+` (resp. `-`) indicating that the parameter is covariant (resp. contravariant), and an injectivity annotation `!` indicating that the parameter can be deduced from the whole type. These type parameters can appear in the type expressions of the right-hand side of the definition, optionally restricted by a variance constraint; i.e. a covariant parameter may only appear on the right side of a functional arrow (more precisely, follow the left branch of an even number of arrows), and a contravariant parameter only the left side (left branch of an odd number of arrows). If the type has a representation or an equation, and the parameter is free (i.e. not bound via a type constraint to a constructed type), its variance constraint is checked but subtyping *etc.* will use the inferred variance of the parameter, which may be less restrictive; otherwise (i.e. for abstract types or non-free parameters), the variance must be given explicitly, and the parameter is invariant if no variance is given.

The optional type equation `= typexpr` makes the defined type equivalent to the type expression `typexpr`: one can be substituted for the other during typing. If no type equation is given, a new type is generated: the defined type is incompatible with any other type.

The optional type representation describes the data structure representing the defined type, by giving the list of associated constructors (if it is a variant type) or associated fields (if it is a record type). If no type representation is given, nothing is assumed on the structure of the type besides what is stated in the optional type equation.

The type representation `= [l] constr-decl { | constr-decl }` describes a variant type. The constructor declarations `constr-decl₁, ..., constr-declₙ` describe the constructors associated to this variant type. The constructor declaration `constr-name of typexpr₁ * ... * typexprₙ` declares the name `constr-name` as a non-constant constructor, whose arguments have types `typexpr₁ ... typexprₙ`. The constructor declaration `constr-name` declares the name `constr-name` as a constant constructor. Constructor names must be capitalized.
## Lazy expressions

The expression `lazy expr` returns a value `v` of type `Lazy.t` that encapsulates the computation of `expr`. The argument `expr` is not evaluated at this point in the program. Instead, its evaluation will be performed the first time the function `Lazy.force` is applied to the value `v`, returning the actual value of `expr`. Subsequent applications of `Lazy.force` to `v` do not evaluate `expr` again. Applications of `Lazy.force` may be implicit through pattern matching (see 11.6.1).

``` OCaml
# let lazy_greeter = lazy (print_string "Hello, World!\n");
val lazy_greeter : unit lazy_t = <lazy>

# Lazy.force lazy_greeter;,
Hello, World!
- : unit = ()
```

## Local modules

The expression `let module module-name = module-expr in expr` locally binds the module expression `module-expr` to the identifier `module-name` during the evaluation of the expression `expr`. It then returns the value of `expr`. For example:

``` OCaml
# let remove_duplicates comparison Fun string_list =
  let module StringSet =
    Set.Make(struct type t = string
              let compare = comparison Fun end)
  in
  StringSets
  (List.fold_right StringSet.add string_list StringSet.empty);;
val remove_duplicates :
  (string -> string -> int) -> string list -> string list = <fun>
```

## Local opens

The expressions `let open module-path in expr` and `module-path . ( expr )` are strictly equivalent. These constructions locally open the module referred to by the module path `module-path` in the respective scope of the expression `expr`.

``` OCaml
# let map_3d_matrix f m =
  let open Array in
  map (map (map f)) m

let map_3d_matrix' f =
  Array.(map (map (map f)));;
val map_3d_matrix :
  ('a -> 'b) -> 'a array array array -> 'b array array array = <fun>
val map_3d_matrix' :
  ('a -> 'b) -> 'a array array array -> 'b array array array = <fun>
```
The type representation = { field-decl {; field-decl} [;] } describes a record type. The field declarations field-decl₁, ..., field-declₙ describe the fields associated to this record type. The field declaration field-name : poly-typexpr declares field-name as a field whose argument has type poly-typexpr. The field declaration mutable field-name : poly-typexpr behaves similarly; in addition, it allows physical modification of this field. Immutable fields are covariant, mutable fields are non-variant. Both mutable and immutable fields may have explicitly polymorphic types. The polymorphism of the contents is statically checked whenever a record value is created or modified. Extracted values may have their types instantiated.

The two components of a type definition, the optional equation and the optional representation, can be combined independently, giving rise to four typical situations:

**Abstract type: no equation, no representation.**

When appearing in a module signature, this definition specifies nothing on the type constructor, besides its number of parameters: its representation is hidden and it is assumed incompatible with any other type.

**Type abbreviation: an equation, no representation.**

This defines the type constructor as an abbreviation for the type expression on the right of the = sign.

**New variant type or record type: no equation, a representation.**

This generates a new type constructor and defines associated constructors or fields, through which values of that type can be directly built or inspected.

**Re-exported variant type or record type: an equation, a representation.**

In this case, the type constructor is defined as an abbreviation for the type expression given in the equation, but in addition the constructors or fields given in the representation remain attached to the defined type constructor. The type expression in the equation part must agree with the representation: it must be of the same kind (record or variant) and have exactly the same constructors or fields, in the same order, with the same arguments. Moreover, the new type constructor must have the same arity and the same type constraints as the original type constructor.

The type variables appearing as type parameters can optionally be prefixed by `+` or `-` to indicate that the type constructor is covariant or contravariant with respect to this parameter. This variance information is used to decide subtyping relations when checking the validity of `>:` coercions (see section 11.7.9).

For instance, `type +'a t` declares `t` as an abstract type that is covariant in its parameter; this means that if the type `τ` is a subtype of the type `σ`, then `τ t` is a subtype of `σ t`. Similarly, `type -:a t` declares that the abstract type `t` is contravariant in its parameter: if `τ` is a subtype of `σ`, then `σ t` is a subtype of `τ t`. If `+` or `-` variance annotation is given, the type constructor is assumed non-variant in the corresponding parameter. For instance, the abstract type declaration `type 'a t` means that `τ t` is neither a subtype nor a supertype of `σ t` if `τ` is subtype of `σ`.

The variance indicated by the `+` and `-` annotations on parameters is enforced only for abstract and private types, or when there are type constraints. Otherwise, for abbreviations, variant and record types without type constraints, the variance properties of the type constructor are inferred from its definition, and the variance annotations are only checked for conformance with the definition.
When the body of a local open expression is delimited by `[]`, `| |`, or `{ }`, the parentheses can be omitted. For expression, parentheses can also be omitted for `{ < > }`. For example, `module-path . [ expr ]` is equivalent to `module-path . ([ expr ])`, and `module-path . [ | expr | ]` is equivalent to `module-path . ([ | expr |])`.

```hml
# let vector = Random.[|int 255; int 255; int 255; int 255|];
val vector : int array = [|220; 90; 247; 144|]
```

# 11.8 Type and exception definitions

## 11.8.1 Type definitions

Type definitions bind type constructors to data types: either variant types, record types, type abbreviations, or abstract data types. They also bind the value constructors and record fields associated with the definition.

```
type-definition ::= type [nonrec] typedef {and typedef}

typedef ::= [type-params] typeconstr-name type-information

type-information ::= [type-equation] [type-representation] {type-constraint}

type-equation ::= = typexpr

type-representation ::= = [|] constr-decl {| constr-decl}
                       | = record-decl
                       | = |

type-params ::= type-param
               | ( type-param {, type-param} )

type-param ::= [ext-variance] ' ident

ext-variance ::= variance [injectivity]
               | injectivity [variance]

variance ::= +
             | -

injectivity ::= !

record-decl ::= { field-decl {; field-decl} [;] }

constr-decl ::= (constr-name | [] | (:*)) [of constr-args]

constr-args ::= typexpr {* typexpr}

field-decl ::= [mutable] field-name : poly-typexpr

type-constraint ::= constraint typexpr = typexpr
```

See also the following language extensions: private types, generalized algebraic datatypes, attributes, extension nodes, extensible variant types and inline records.
Injectivity annotations are only necessary for abstract types and private row types, since they can otherwise be deduced from the type declaration: all parameters are injective for record and variant type declarations (including extensible types); for type abbreviations a parameter is injective if it has an injective occurrence in its defining equation (be it private or not). For constrained type parameters in type abbreviations, they are injective if either they appear at an injective position in the body, or if all their type variables are injective; in particular, if a constrained type parameter contains a variable that doesn't appear in the body, it cannot be injective.

The construct `constraint ' ident = typexpr` allows the specification of type parameters. Any actual type argument corresponding to the type parameter `ident` has to be an instance of `typexpr` (more precisely, `ident` and `typexpr` are unified). Type variables of `typexpr` can appear in the type equation and the type declaration.

### 11.8.2 Exception definitions

```
exception-definition ::= exception constr-decl
                       | exception constr-name = constr
```

Exception definitions add new constructors to the built-in variant type `exn` of exception values. The constructors are declared as for a definition of a variant type.

```
# exception E of int * string;;
exception E of int * string
```

The form `exception constr-decl` generates a new exception, distinct from all other exceptions in the system. The form `exception constr-name = constr` gives an alternate name to an existing exception.

```
# exception E of int * string
```

```
exception F = E
```

```
let eq =
```

```
E (1, "one") = F (1, "one");
```

```
exception E of int * string
exception F of int * string
```

```
val eq : bool = true
```

## 11.9 Classes

Classes are defined using a small language, similar to the module language.

### 11.9.1 Class types

Class types are the class-level equivalent of type expressions: they specify the general shape and type properties of classes.
Type definitions are introduced by the `type` keyword, and consist in one or several simple definitions, possibly mutually recursive, separated by the `and` keyword. Each simple definition defines one type constructor.

A simple definition consists in a lowercase identifier, possibly preceded by one or several type parameters, and followed by an optional type equation, then an optional type representation, and then a constraint clause. The identifier is the name of the type constructor being defined.

```ocaml
type colour =
  | Red | Green | Blue | Yellow | Black | White
  | RGB of {r : int; g : int; b : int}
```

```ocaml
type 'a tree = Lf | Br of 'a * 'a tree * 'a;;
```

```ocaml
type t = {decoration : string; substance : t'}
and t' = Int of int | List of t list
```

In the right-hand side of type definitions, references to one of the type constructor name being defined are considered as recursive, unless `type` is followed by `nonrec`. The `nonrec` keyword was introduced in OCaml 4.02.2.

The optional type parameters are either one type variable `'ident'`, for type constructors with one parameter, or a list of type variables (`'ident₁, ..., 'identₙ`), for type constructors with several parameters. Each type parameter may be prefixed by a variance constraint `+` (resp. `-`) indicating that the parameter is covariant (resp. contravariant), and an injectivity annotation `!` indicating that the parameter can be deduced from the whole type. These type parameters can appear in the type expressions of the right-hand side of the definition, optionally restricted by a variance constraint; i.e. a covariant parameter may only appear on the right side of a functional arrow (more precisely, follow the left branch of an even number of arrows), and a contravariant parameter only the left side (left branch of an odd number of arrows). If the type has a representation or an equation, and the parameter is free (i.e. not bound via a type constraint to a constructed type), its variance constraint is checked but subtyping *etc.* will use the inferred variance of the parameter, which may be less restrictive; otherwise (i.e. for abstract types or non-free parameters), the variance must be given explicitly, and the parameter is invariant if no variance is given.

The optional type equation `= typexpr` makes the defined type equivalent to the type expression `typexpr`: one can be substituted for the other during typing. If no type equation is given, a new type is generated: the defined type is incompatible with any other type.

The optional type representation describes the data structure representing the defined type, by giving the list of associated constructors (if it is a variant type) or associated fields (if it is a record type). If no type representation is given, nothing is assumed on the structure of the type besides what is stated in the optional type equation.

The type representation `= [l] constr-decl { | constr-decl }` describes a variant type. The constructor declarations `constr-decl₁, ..., constr-declₙ` describe the constructors associated to this variant type. The constructor declaration `constr-name of typexpr₁ * ... * typexprₙ` declares the name `constr-name` as a non-constant constructor, whose arguments have types `typexpr₁ ... typexprₙ`. The constructor declaration `constr-name` declares the name `constr-name` as a constant constructor. Constructor names must be capitalized.
<table><tr><td>class-type</td><td>::=</td><td>[[?] label-name :] typexpr &rarr; class-type<br/>&nbsp;&nbsp;&nbsp;&nbsp;|<br/>&nbsp;&nbsp;&nbsp;&nbsp;class-body-type</td></tr><tr><td>class-body-type</td><td>::=</td><td>object [( typexpr )] {class-field-spec} end<br/>&nbsp;&nbsp;&nbsp;&nbsp;| [[ typexpr {, typexpr} ]] classtype-path<br/>&nbsp;&nbsp;&nbsp;&nbsp;| let open module-path in class-body-type</td></tr><tr><td>class-field-spec</td><td>::=</td><td>inherit class-body-type<br/>&nbsp;&nbsp;&nbsp;&nbsp;| val [mutable] [virtual] inst-var-name : typexpr<br/>&nbsp;&nbsp;&nbsp;&nbsp;| val virtual mutable inst-var-name : typexpr<br/>&nbsp;&nbsp;&nbsp;&nbsp;| method [private] [virtual] method-name : poly-typexpr<br/>&nbsp;&nbsp;&nbsp;&nbsp;| method virtual private method-name : poly-typexpr<br/>&nbsp;&nbsp;&nbsp;&nbsp;| constraint typexpr = typexpr</td></tr></table>

See also the following language extensions: attributes and extension nodes.

## Simple class expressions

The expression `classtype-path` is equivalent to the class type bound to the name `classtype-path`. Similarly, the expression `[ typexpr₁, ..., typexprₙ ] classtype-path` is equivalent to the parametric class type bound to the name `classtype-path`, in which type parameters have been instantiated to respectively `typexpr₁, ..., typexprₙ`.

## Class function type

The class type expression `typexpr -> class-type` is the type of class functions (functions from values to classes) that take as argument a value of type `typexpr` and return as result a class of type `class-type`.

## Class body type

The class type expression `object [( typexpr )] {class-field-spec} end` is the type of a class body. It specifies its instance variables and methods. In this type, `typexpr` is matched against the self type, therefore providing a name for the self type.

A class body will match a class body type if it provides definitions for all the components specified in the class body type, and these definitions meet the type requirements given in the class body type. Furthermore, all methods either virtual or public present in the class body must also be present in the class body type (on the other hand, some instance variables and concrete private methods may be omitted). A virtual method will match a concrete method, which makes it possible to forget its implementation. An immutable instance variable will match a mutable instance variable.

## Local opens

Local opens are supported in class types since OCaml 4.06.
The type representation = { field-decl {; field-decl} [;] } describes a record type. The field declarations field-decl₁, ..., field-declₙ describe the fields associated to this record type. The field declaration field-name : poly-typexpr declares field-name as a field whose argument has type poly-typexpr. The field declaration mutable field-name : poly-typexpr behaves similarly; in addition, it allows physical modification of this field. Immutable fields are covariant, mutable fields are non-variant. Since OCaml 5.4, mutable fields may be marked[@atomic] for concurrent access, see 9.7.2.

Both mutable and immutable fields may have explicitly polymorphic types. The polymorphism of the contents is statically checked whenever a record value is created or modified. Extracted values may have their types instantiated.

The two components of a type definition, the optional equation and the optional representation, can be combined independently, giving rise to four typical situations:

**Abstract type: no equation, no representation.**

When appearing in a module signature, this definition specifies nothing on the type constructor, besides its number of parameters: its representation is hidden and it is assumed incompatible with any other type.

**Type abbreviation: an equation, no representation.**

This defines the type constructor as an abbreviation for the type expression on the right of the = sign.

**New variant type or record type: no equation, a representation.**

This generates a new type constructor and defines associated constructors or fields, through which values of that type can be directly built or inspected.

**Re-exported variant type or record type: an equation, a representation.**

In this case, the type constructor is defined as an abbreviation for the type expression given in the equation, but in addition the constructors or fields given in the representation remain attached to the defined type constructor. The type expression in the equation part must agree with the representation: it must be of the same kind (record or variant) and have exactly the same constructors or fields, in the same order, with the same arguments. Moreover, the new type constructor must have the same arity and the same type constraints as the original type constructor.

The type variables appearing as type parameters can optionally be prefixed by + or - to indicate that the type constructor is covariant or contravariant with respect to this parameter. This variance information is used to decide subtyping relations when checking the validity of :> coercions (see section 11.7.9).

For instance, type +'a t declares t as an abstract type that is covariant in its parameter; this means that if the type τ is a subtype of the type σ, then τ t is a subtype of σ t. Similarly, type -'a t declares that the abstract type t is contravariant in its parameter: if τ is a subtype of σ, then σ t is a subtype of τ t. If no + or - variance annotation is given, the type constructor is assumed non-variant in the corresponding parameter. For instance, the abstract type declaration type 'a t means that τ t is neither a subtype nor a supertype of σ t if τ is subtype of σ.

The variance indicated by the + and - annotations on parameters is enforced only for abstract and private types, or when there are type constraints. Otherwise, for abbreviations, variant and record
## Inheritance

The inheritance construct `inherit class-body-type` provides for inclusion of methods and instance variables from other class types. The instance variable and method types from `class-body-type` are added into the current class type.

## Instance variable specification

A specification of an instance variable is written `val [mutable] [virtual] inst-var-name : typexpr`, where `inst-var-name` is the name of the instance variable and `typexpr` its expected type. The flag `mutable` indicates whether this instance variable can be physically modified. The flag `virtual` indicates that this instance variable is not initialized. It can be initialized later through inheritance.

An instance variable specification will hide any previous specification of an instance variable of the same name.

## Method specification

The specification of a method is written `method [private] method-name : poly-typexpr`, where `method-name` is the name of the method and `poly-typexpr` its expected type, possibly polymorphic. The flag `private` indicates that the method cannot be accessed from outside the object.

The polymorphism may be left implicit in public method specifications: any type variable which is not bound to a class parameter and does not appear elsewhere inside the class specification will be assumed to be universal, and made polymorphic in the resulting method type. Writing an explicit polymorphic type will disable this behaviour.

If several specifications are present for the same method, they must have compatible types. Any non-private specification of a method forces it to be public.

## Virtual method specification

A virtual method specification is written `method [private] virtual method-name : poly-typexpr`, where `method-name` is the name of the method and `poly-typexpr` its expected type.

## Constraints on type parameters

The construct `constraint typexpr₁ = typexpr₂` forces the two type expressions to be equal. This is typically used to specify type parameters: in this way, they can be bound to specific type expressions.

## 11.9.2 Class expressions

Class expressions are the class-level equivalent of value expressions: they evaluate to classes, thus providing implementations for the specifications expressed in class types.
types without type constraints, the variance properties of the type constructor are inferred from its definition, and the variance annotations are only checked for conformance with the definition.

Injectivity annotations are only necessary for abstract types and private row types, since they can otherwise be deduced from the type declaration: all parameters are injective for record and variant type declarations (including extensible types); for type abbreviations a parameter is injective if it has an injective occurrence in its defining equation (be it private or not). For constrained type parameters in type abbreviations, they are injective if either they appear at an injective position in the body, or if all their type variables are injective; in particular, if a constrained type parameter contains a variable that doesn't appear in the body, it cannot be injective.

The construct `constraint ' ident = typexpr` allows the specification of type parameters. Any actual type argument corresponding to the type parameter `ident` has to be an instance of `typexpr` (more precisely, `ident` and `typexpr` are unified). Type variables of `typexpr` can appear in the type equation and the type declaration.

### 11.8.2 Exception definitions

```
exception-definition ::= exception constr-decl
                       | exception constr-name = constr
```

Exception definitions add new constructors to the built-in variant type `exn` of exception values. The constructors are declared as for a definition of a variant type.

```
# exception E of int * string;;
exception E of int * string
```

The form `exception constr-decl` generates a new exception, distinct from all other exceptions in the system. The form `exception constr-name = constr` gives an alternate name to an existing exception.

```
# exception E of int * string
exception F = E
```

```
let eq = 
    E (1, "one") = F (1, "one");
exception E of int * string
exception F of int * string
val eq : bool = true
```

## 11.9 Classes

Classes are defined using a small language, similar to the module language.

### 11.9.1 Class types

Class types are the class-level equivalent of type expressions: they specify the general shape and type properties of classes.
class-expr ::= class-path
             | [ typexpr {, typexpr} ] class-path
             | ( class-expr )
             | ( class-expr : class-type )
             | class-expr {argument}+
             | fun {parameter}+ -> class-expr
             | let [rec] let-binding {and let-binding} in class-expr
             | object class-body end
             | let open module-path in class-expr

class-field ::= inherit class-expr [as lowercase-ident]
               | inherit! class-expr [as lowercase-ident]
               | val [mutable] inst-var-name [: typexpr] = expr
               | val! [mutable] inst-var-name [: typexpr] = expr
               | val [mutable] virtual inst-var-name : typexpr
               | val virtual mutable inst-var-name : typexpr
               | method [private] method-name {parameter} [: typexpr] = expr
               | method! [private] method-name {parameter} [: typexpr] = expr
               | method [private] method-name : poly-typexpr = expr
               | method! [private] method-name : poly-typexpr = expr
               | method [private] virtual method-name : poly-typexpr
               | method virtual private method-name : poly-typexpr
               | constraint typexpr = typexpr
               | initializer expr

See also the following language extensions: locally abstract types, attributes and extension nodes.

## Simple class expressions

The expression *class-path* evaluates to the class bound to the name *class-path*. Similarly, the expression `[ typexpr₁, ..., typexprₙ ] class-path` evaluates to the parametric class bound to the name *class-path*, in which type parameters have been instantiated respectively to *typexpr₁, ..., typexprₙ*.

The expression `( class-expr )` evaluates to the same module as *class-expr*.

The expression `( class-expr : class-type )` checks that *class-type* matches the type of *class-expr* (that is, that the implementation *class-expr* meets the type specification *class-type*). The whole expression evaluates to the same class as *class-expr*, except that all components not specified in *class-type* are hidden and can no longer be accessed.

## Class application

Class application is denoted by juxtaposition of (possibly labeled) expressions. It denotes the class whose constructor is the first expression applied to the given arguments. The arguments are evaluated as for expression application, but the constructor itself will only be evaluated when objects
class-type ::= [[?] label-name :] typexpr -> class-type
             | class-body-type

class-body-type ::= object [( typexpr )] {class-field-spec} end
                    | [[ typexpr {, typexpr} ]] classtype-path
                    | let open module-path in class-body-type

class-field-spec ::= inherit class-body-type
                    | val [mutable] [virtual] inst-var-name : typexpr
                    | val virtual mutable inst-var-name : typexpr
                    | method [private] [virtual] method-name : poly-typexpr
                    | method virtual private method-name : poly-typexpr
                    | constraint typexpr = typexpr

See also the following language extensions: *attributes* and *extension nodes*.

## Simple class expressions

The expression *classtype-path* is equivalent to the class type bound to the name *classtype-path*. Similarly, the expression `[ typexpr₁, ..., typexprₙ ] classtype-path` is equivalent to the parametric class type bound to the name *classtype-path*, in which type parameters have been instantiated to respectively *typexpr₁, ..., typexprₙ*.

## Class function type

The class type expression `typexpr -> class-type` is the type of class functions (functions from values to classes) that take as argument a value of type `typexpr` and return as result a class of type *class-type*.

## Class body type

The class type expression `object [( typexpr )] {class-field-spec} end` is the type of a class body. It specifies its instance variables and methods. In this type, `typexpr` is matched against the self type, therefore providing a name for the self type.

A class body will match a class body type if it provides definitions for all the components specified in the class body type, and these definitions meet the type requirements given in the class body type. Furthermore, all methods either virtual or public present in the class body must also be present in the class body type (on the other hand, some instance variables and concrete private methods may be omitted). A virtual method will match a concrete method, which makes it possible to forget its implementation. An immutable instance variable will match a mutable instance variable.

## Local opens

Local opens are supported in class types since OCaml 4.06.
are created. In particular, side-effects caused by the application of the constructor will only occur at object creation time.

## Class function

The expression `fun [?] label-name :] pattern -> class-expr` evaluates to a function from values to classes. When this function is applied to a value `v`, this value is matched against the pattern `pattern` and the result is the result of the evaluation of `class-expr` in the extended environment.

Conversion from functions with default values to functions with patterns only works identically for class functions as for normal functions.

The expression

`fun parameter₁... parameterₙ -> class-expr`

is a short form for

`fun parameter₁ -> ... fun parameterₙ -> expr`

## Local definitions

The `let` and `let rec` constructs bind value names locally, as for the core language expressions.

If a local definition occurs at the very beginning of a class definition, it will be evaluated when the class is created (just as if the definition was outside of the class). Otherwise, it will be evaluated when the object constructor is called.

## Local opens

Local opens are supported in class expressions since OCaml 4.06.

## Class body

`class-body ::= [( pattern [ : typexpr ] )] {class-field}`

The expression `object class-body end` denotes a class body. This is the prototype for an object: it lists the instance variables and methods of an object of this class.

A class body is a class value: it is not evaluated at once. Rather, its components are evaluated each time an object is created.

In a class body, the pattern `( pattern [ : typexpr ] )` is matched against self, therefore providing a binding for self and self type. Self can only be used in method and initializers.

Self type cannot be a closed object type, so that the class remains extensible.

Since OCaml 4.01, it is an error if the same method or instance variable name is defined several times in the same class body.

## Inheritance

The inheritance construct `inherit class-expr` allows reusing methods and instance variables from other classes. The class expression `class-expr` must evaluate to a class body. The instance variables, methods and initializers from this class body are added into the current class. The addition of a method will override any previously defined method of the same name.
## Inheritance

The inheritance construct `inherit class-body-type` provides for inclusion of methods and instance variables from other class types. The instance variable and method types from `class-body-type` are added into the current class type.

## Instance variable specification

A specification of an instance variable is written `val [mutable] [virtual] inst-var-name : typexpr`, where `inst-var-name` is the name of the instance variable and `typexpr` its expected type. The flag `mutable` indicates whether this instance variable can be physically modified. The flag `virtual` indicates that this instance variable is not initialized. It can be initialized later through inheritance.

An instance variable specification will hide any previous specification of an instance variable of the same name.

## Method specification

The specification of a method is written `method [private] method-name : poly-typexpr`, where `method-name` is the name of the method and `poly-typexpr` its expected type, possibly polymorphic. The flag `private` indicates that the method cannot be accessed from outside the object.

The polymorphism may be left implicit in public method specifications: any type variable which is not bound to a class parameter and does not appear elsewhere inside the class specification will be assumed to be universal, and made polymorphic in the resulting method type. Writing an explicit polymorphic type will disable this behaviour.

If several specifications are present for the same method, they must have compatible types. Any non-private specification of a method forces it to be public.

## Virtual method specification

A virtual method specification is written `method [private] virtual method-name : poly-typexpr`, where `method-name` is the name of the method and `poly-typexpr` its expected type.

## Constraints on type parameters

The construct `constraint typexpr₁ = typexpr₂` forces the two type expressions to be equal. This is typically used to specify type parameters: in this way, they can be bound to specific type expressions.

## 11.9.2 Class expressions

Class expressions are the class-level equivalent of value expressions: they evaluate to classes, thus providing implementations for the specifications expressed in class types.
An ancestor can be bound by appending **as lowercase-ident** to the inheritance construct. **lowercase-ident** is not a true variable and can only be used to select a method, i.e. in an expression **lowercase-ident** # **method-name**. This gives access to the method **method-name** as it was defined in the parent class even if it is redefined in the current class. The scope of this ancestor binding is limited to the current class. The ancestor method may be called from a subclass but only indirectly.

## Instance variable definition

The definition `val [mutable] inst-var-name = expr` adds an instance variable `inst-var-name` whose initial value is the value of expression `expr`. The flag `mutable` allows physical modification of this variable by methods.

An instance variable can only be used in the methods and initializers that follow its definition.

Since version 3.10, redefinitions of a visible instance variable with the same name do not create a new variable, but are merged, using the last value for initialization. They must have identical types and mutability. However, if an instance variable is hidden by omitting it from an interface, it will be kept distinct from other instance variables with the same name.

## Virtual instance variable definition

A variable specification is written `val [mutable] virtual inst-var-name : typexpr`. It specifies whether the variable is modifiable, and gives its type.

Virtual instance variables were added in version 3.10.

## Method definition

A method definition is written `method method-name = expr`. The definition of a method overrides any previous definition of this method. The method will be public (that is, not private) if any of the definition states so.

A private method, `method private method-name = expr`, is a method that can only be invoked on self (from other methods of the same object, defined in this class or one of its subclasses). This invocation is performed using the expression `value-name # method-name`, where `value-name` is directly bound to self at the beginning of the class definition. Private methods do not appear in object types. A method may have both public and private definitions, but as soon as there is a public one, all subsequent definitions will be made public.

Methods may have an explicitly polymorphic type, allowing them to be used polymorphically in programs (even for the same object). The explicit declaration may be done in one of three ways: (1) by giving an explicit polymorphic type in the method definition, immediately after the method name, i.e. `method [private] method-name : { ' ident } + . typexpr = expr;` (2) by a forward declaration of the explicit polymorphic type through a virtual method definition; (3) by importing such a declaration through inheritance and/or constraining the type of `self`.

Some special expressions are available in method bodies for manipulating instance variables and duplicating self:

```
expr ::= ...
| inst-var-name <- expr
| {< [inst-var-name = expr {; inst-var-name = expr} [;]] >}
```
class-expr ::= class-path
             | [ typexpr {, typexpr} ] class-path
             | ( class-expr )
             | ( class-expr : class-type )
             | class-expr {argument}+
             | fun {parameter}+ -> class-expr
             | let [rec] let-binding {and let-binding} in class-expr
             | object class-body end
             | let open module-path in class-expr

class-field ::= inherit class-expr [as lowercase-ident]
               | inherit! class-expr [as lowercase-ident]
               | val [mutable] inst-var-name [: typexpr] = expr
               | val! [mutable] inst-var-name [: typexpr] = expr
               | val [mutable] virtual inst-var-name : typexpr
               | val virtual mutable inst-var-name : typexpr
               | method [private] method-name {parameter} [: typexpr] = expr
               | method! [private] method-name {parameter} [: typexpr] = expr
               | method [private] method-name : poly-typexpr = expr
               | method! [private] method-name : poly-typexpr = expr
               | method [private] virtual method-name : poly-typexpr
               | method virtual private method-name : poly-typexpr
               | constraint typexpr = typexpr
               | initializer expr

See also the following language extensions: locally abstract types, attributes and extension nodes.

## Simple class expressions

The expression *class-path* evaluates to the class bound to the name *class-path*. Similarly, the expression `[ typexpr₁, ..., typexprₙ ] class-path` evaluates to the parametric class bound to the name *class-path*, in which type parameters have been instantiated respectively to *typexpr₁, ..., typexprₙ*.

The expression `( class-expr )` evaluates to the same module as *class-expr*.

The expression `( class-expr : class-type )` checks that *class-type* matches the type of *class-expr* (that is, that the implementation *class-expr* meets the type specification *class-type*). The whole expression evaluates to the same class as *class-expr*, except that all components not specified in *class-type* are hidden and can no longer be accessed.

## Class application

Class application is denoted by juxtaposition of (possibly labeled) expressions. It denotes the class whose constructor is the first expression applied to the given arguments. The arguments are evaluated as for expression application, but the constructor itself will only be evaluated when objects
The expression `inst-var-name <- expr` modifies in-place the current object by replacing the value associated to `inst-var-name` by the value of `expr`. Of course, this instance variable must have been declared mutable.

The expression `{< inst-var-name₁ = expr₁ ; ... ; inst-var-nameₙ = exprₙ >}` evaluates to a copy of the current object in which the values of instance variables `inst-var-name₁`, ..., `inst-var-nameₙ` have been replaced by the values of the corresponding expressions `expr₁`, ..., `exprₙ`.

### Virtual method definition

A method specification is written `method [private] virtual method-name : poly-typexpr`. It specifies whether the method is public or private, and gives its type. If the method is intended to be polymorphic, the type must be explicitly polymorphic.

### Explicit overriding

Since Ocaml 3.12, the keywords `inherit!`, `val!` and `method!` have the same semantics as `inherit`, `val` and `method`, but they additionally require the definition they introduce to be overriding. Namely, `method!` requires `method-name` to be already defined in this class, `val!` requires `inst-var-name` to be already defined in this class, and `inherit!` requires `class-expr` to override some definitions. If no such overriding occurs, an error is signaled.

As a side-effect, these 3 keywords avoid the warnings 7 (method override) and 13 (instance variable override). Note that warning 7 is disabled by default.

### Constraints on type parameters

The construct `constraint typexpr₁ = typexpr₂` forces the two type expressions to be equals. This is typically used to specify type parameters: in that way they can be bound to specific type expressions.

### Initializers

A class initializer ` initializer` `expr` specifies an expression that will be evaluated whenever an object is created from the class, once all its instance variables have been initialized.

### 11.9.3 Class definitions

`class-definition ::= class class-binding {and class-binding}`

`class-binding ::= [virtual] [[type-parameters]] class-name {parameter} [: class-type] = class-expr`

`type-parameters ::= 'ident {, 'ident}`

A class definition `class class-binding {and class-binding}` is recursive. Each `class-binding` defines a `class-name` that can be used in the whole expression except for inheritance. It can also be used for inheritance, but only in the definitions that follow its own.

A class binding binds the class name `class-name` to the value of expression `class-expr`. It also binds the class type `class-name` to the type of the class, and defines two type abbreviations : `class-name` and `# class-name`. The first one is the type of objects of this class, while the second is more general as it unifies with the type of any object belonging to a subclass (see section 11.4).
are created. In particular, side-effects caused by the application of the constructor will only occur at object creation time.

## Class function

The expression `fun [?] label-name :] pattern -> class-expr` evaluates to a function from values to classes. When this function is applied to a value `v`, this value is matched against the pattern `pattern` and the result is the result of the evaluation of `class-expr` in the extended environment.

Conversion from functions with default values to functions with patterns only works identically for class functions as for normal functions.

The expression

`fun parameter₁ ... parameterₙ -> class-expr`

is a short form for

`fun parameter₁ -> ... fun parameterₙ -> expr`

## Local definitions

The `let` and `let rec` constructs bind value names locally, as for the core language expressions.

If a local definition occurs at the very beginning of a class definition, it will be evaluated when the class is created (just as if the definition was outside of the class). Otherwise, it will be evaluated when the object constructor is called.

## Local opens

Local opens are supported in class expressions since OCaml 4.06.

## Class body

`class-body ::= [( pattern [: typexpr ] )] {class-field}`

The expression `object class-body end` denotes a class body. This is the prototype for an object: it lists the instance variables and methods of an object of this class.

A class body is a class value: it is not evaluated at once. Rather, its components are evaluated each time an object is created.

In a class body, the pattern `( pattern [: typexpr ] )` is matched against self, therefore providing a binding for self and self type. Self can only be used in method and initializers.

Self type cannot be a closed object type, so that the class remains extensible.

Since OCaml 4.01, it is an error if the same method or instance variable name is defined several times in the same class body.
## Virtual class

A class must be flagged virtual if one of its methods is virtual (that is, appears in the class type, but is not actually defined). Objects cannot be created from a virtual class.

## Type parameters

The class type parameters correspond to the ones of the class type and of the two type abbreviations defined by the class binding. They must be bound to actual types in the class definition using type constraints. So that the abbreviations are well-formed, type variables of the inferred type of the class must either be type parameters or be bound in the constraint clause.

### 11.9.4 Class specifications

`class-specification ::= class class-spec {and class-spec}`

`class-spec ::= [virtual] [[type-parameters]] class-name : class-type`

This is the counterpart in signatures of class definitions. A class specification matches a class definition if they have the same type parameters and their types match.

### 11.9.5 Class type definitions

`classtype-definition ::= class type classtype-def {and classtype-def}`

`classtype-def ::= [virtual] [[type-parameters]] class-name = class-body-type`

A class type definition `class class-name = class-body-type` defines an abbreviation `class-name` for the class body type `class-body-type`. As for class definitions, two type abbreviations `class-name` and `# class-name` are also defined. The definition can be parameterized by some type parameters. If any method in the class type body is virtual, the definition must be flagged `virtual`.

Two class type definitions match if they have the same type parameters and they expand to matching types.

## 11.10 Module types (module specifications)

Module types are the module-level equivalent of type expressions: they specify the general shape and type properties of modules.

`module-type ::= modtype-path
| sig {specification [;;]} end
| functor ( module-name : module-type ) -> module-type
| module-type -> module-type
| module-type with mod-constraint {and mod-constraint}
| ( module-type )`

`mod-constraint ::= type [type-params] typeconstr type-equation {type-constraint}
| module module-path = extended-module-path`
## Inheritance

The inheritance construct `inherit class-expr` allows reusing methods and instance variables from other classes. The class expression `class-expr` must evaluate to a class body. The instance variables, methods and initializers from this class body are added into the current class. The addition of a method will override any previously defined method of the same name.

An ancestor can be bound by appending **as lowercase-ident** to the inheritance construct. `lowercase-ident` is not a true variable and can only be used to select a method, i.e. in an expression `lowercase-ident # method-name`. This gives access to the method `method-name` as it was defined in the parent class even if it is redefined in the current class. The scope of this ancestor binding is limited to the current class. The ancestor method may be called from a subclass but only indirectly.

## Instance variable definition

The definition `val [mutable] inst-var-name = expr` adds an instance variable `inst-var-name` whose initial value is the value of expression `expr`. The flag `mutable` allows physical modification of this variable by methods.

An instance variable can only be used in the methods and initializers that follow its definition.

Since version 3.10, redefinitions of a visible instance variable with the same name do not create a new variable, but are merged, using the last value for initialization. They must have identical types and mutability. However, if an instance variable is hidden by omitting it from an interface, it will be kept distinct from other instance variables with the same name.

## Virtual instance variable definition

A variable specification is written `val [mutable] virtual inst-var-name : typexpr`. It specifies whether the variable is modifiable, and gives its type.

Virtual instance variables were added in version 3.10.

## Method definition

A method definition is written `method method-name = expr`. The definition of a method overrides any previous definition of this method. The method will be public (that is, not private) if any of the definition states so.

A private method, `method private method-name = expr`, is a method that can only be invoked on self (from other methods of the same object, defined in this class or one of its subclasses). This invocation is performed using the expression `value-name # method-name`, where `value-name` is directly bound to self at the beginning of the class definition. Private methods do not appear in object types. A method may have both public and private definitions, but as soon as there is a public one, all subsequent definitions will be made public.

Methods may have an explicitly polymorphic type, allowing them to be used polymorphically in programs (even for the same object). The explicit declaration may be done in one of three ways: (1) by giving an explicit polymorphic type in the method definition, immediately after the method name, i.e. `method [private] method-name : {' ident} + . typexpr = expr`; (2) by a forward declaration
<table><tr><td>specification</td><td>::=</td><td>val value-name : typexpr</td></tr><tr><td></td><td></td><td>external value-name : typexpr = external-declaration</td></tr><tr><td></td><td></td><td>type-definition</td></tr><tr><td></td><td></td><td>exception constr-decl</td></tr><tr><td></td><td></td><td>class-specification</td></tr><tr><td></td><td></td><td>classtype-definition</td></tr><tr><td></td><td></td><td>module module-name : module-type</td></tr><tr><td></td><td></td><td>module module-name { ( module-name : module-type ) } : module-type</td></tr><tr><td></td><td></td><td>module type modtype-name</td></tr><tr><td></td><td></td><td>module type modtype-name = module-type</td></tr><tr><td></td><td></td><td>open module-path</td></tr><tr><td></td><td></td><td>include module-type</td></tr></table>

See also the following language extensions: recovering the type of a module, substitution inside a signature, type-level module aliases, attributes, extension nodes, generative functors, and module type substitutions.

### 11.10.1 Simple module types

The expression `modtype-path` is equivalent to the module type bound to the name `modtype-path`. The expression `( module-type )` denotes the same type as `module-type`.

### 11.10.2 Signatures

Signatures are type specifications for structures. Signatures `sig...end` are collections of type specifications for value names, type names, exceptions, module names and module type names. A structure will match a signature if the structure provides definitions (implementations) for all the names specified in the signature (and possibly more), and these definitions meet the type requirements given in the signature.

An optional `; ;` is allowed after each specification in a signature. It serves as a syntactic separator with no semantic meaning.

#### Value specifications

A specification of a value component in a signature is written `val value-name : typexpr`, where `value-name` is the name of the value and `typexpr` its expected type.

The form `external value-name : typexpr = external-declaration` is similar, except that it requires in addition the name to be implemented as the external function specified in `external-declaration` (see chapter 22).

#### Type specifications

A specification of one or several type components in a signature is written `type typedef {and typedef}` and consists of a sequence of mutually recursive definitions of type names.

Each type definition in the signature specifies an optional type equation `= typexpr` and an optional type representation `= constr-decl...` or `= { field-decl...}`. The implementation of the type name in a matching structure must be compatible with the type expression specified in the equation
of the explicit polymorphic type through a virtual method definition; (3) by importing such a declaration through inheritance and/or constraining the type of self.

Some special expressions are available in method bodies for manipulating instance variables and duplicating self:

$$ \begin{array}{l} expr ::= \dots \\ | \quad inst-var-name <- expr \\ | \quad {< [inst-var-name = expr {; inst-var-name = expr} [;]] >} \end{array} $$

The expression `inst-var-name <- expr` modifies in-place the current object by replacing the value associated to `inst-var-name` by the value of `expr`. Of course, this instance variable must have been declared mutable.

The expression `{< inst-var-name₁ = expr₁ ; ... ; inst-var-nameₙ = exprₙ >}` evaluates to a copy of the current object in which the values of instance variables `inst-var-name₁`, ..., `inst-var-nameₙ` have been replaced by the values of the corresponding expressions `expr₁`, ..., `exprₙ`.

### Virtual method definition

A method specification is written `method [private] virtual method-name : poly-typexpr`. It specifies whether the method is public or private, and gives its type. If the method is intended to be polymorphic, the type must be explicitly polymorphic.

### Explicit overriding

Since Ocaml 3.12, the keywords `inherit!`, `val!` and `method!` have the same semantics as `inherit`, `val` and `method`, but they additionally require the definition they introduce to be overriding. Namely, `method!` requires `method-name` to be already defined in this class, `val!` requires `inst-var-name` to be already defined in this class, and `inherit!` requires `class-expr` to override some definitions. If no such overriding occurs, an error is signaled.

As a side-effect, these 3 keywords avoid the warnings 7 (method override) and 13 (instance variable override). Note that warning 7 is disabled by default.

### Constraints on type parameters

The construct `constraint typexpr₁ = typexpr₂` forces the two type expressions to be equals. This is typically used to specify type parameters: in that way they can be bound to specific type expressions.

### Initializers

A class initializer ` initializers` `expr` specifies an expression that will be evaluated whenever an object is created from the class, once all its instance variables have been initialized.

### 11.9.3 Class definitions

`class-definition ::= class class-binding {and class-binding}`

`class-binding ::= [virtual] [[type-parameters]] class-name {parameter} [: class-type] = class-expr`

`type-parameters ::= 'ident {, 'ident}`
(if given), and have the specified representation (if given). Conversely, users of that signature will
be able to rely on the type equation or type representation, if given. More precisely, we have the
following four situations:

**Abstract type: no equation, no representation.**

Names that are defined as abstract types in a signature can be implemented in a matching
structure by any kind of type definition (provided it has the same number of type parameters).
The exact implementation of the type will be hidden to the users of the structure. In particular,
if the type is implemented as a variant type or record type, the associated constructors and
fields will not be accessible to the users; if the type is implemented as an abbreviation, the type
equality between the type name and the right-hand side of the abbreviation will be hidden
from the users of the structure. Users of the structure consider that type as incompatible with
any other type: a fresh type has been generated.

**Type abbreviation: an equation = typexpr, no representation.**

The type name must be implemented by a type compatible with *typexpr*. All users of the
structure know that the type name is compatible with *typexpr*.

**New variant type or record type: no equation, a representation.**

The type name must be implemented by a variant type or record type with exactly the
constructors or fields specified. All users of the structure have access to the constructors
or fields, and can use them to create or inspect values of that type. However, users of the
structure consider that type as incompatible with any other type: a fresh type has been
generated.

**Re-exported variant type or record type: an equation, a representation.**

This case combines the previous two: the representation of the type is made visible to all
users, and no fresh type is generated.

**Exception specification**

The specification *exception constr-decl* in a signature requires the matching structure to provide
an exception with the name and arguments specified in the definition, and makes the exception
available to all users of the structure.

**Class specifications**

A specification of one or several classes in a signature is written **class class-spec {and class-spec}**
and consists of a sequence of mutually recursive definitions of class names.

Class specifications are described more precisely in section 11.9.4.

**Class type specifications**

A specification of one or several class types in a signature is written **class type classtype-def {and classtype-def}** and consists of a sequence of mutually recursive definitions of class type names.
Class type specifications are described more precisely in section 11.9.5.
A class definition `class class-binding {and class-binding}` is recursive. Each `class-binding` defines a `class-name` that can be used in the whole expression except for inheritance. It can also be used for inheritance, but only in the definitions that follow its own.

A class binding binds the class name `class-name` to the value of expression `class-expr`. It also binds the class type `class-name` to the type of the class, and defines two type abbreviations: `class-name` and `# class-name`. The first one is the type of objects of this class, while the second is more general as it unifies with the type of any object belonging to a subclass (see section 11.4).

### Virtual class

A class must be flagged virtual if one of its methods is virtual (that is, appears in the class type, but is not actually defined). Objects cannot be created from a virtual class.

### Type parameters

The class type parameters correspond to the ones of the class type and of the two type abbreviations defined by the class binding. They must be bound to actual types in the class definition using type constraints. So that the abbreviations are well-formed, type variables of the inferred type of the class must either be type parameters or be bound in the constraint clause.

### 11.9.4 Class specifications

`class-specification ::= class class-spec {and class-spec}`

`class-spec ::= [virtual] [[type-parameters]] class-name : class-type`

This is the counterpart in signatures of class definitions. A class specification matches a class definition if they have the same type parameters and their types match.

### 11.9.5 Class type definitions

`classtype-definition ::= class type classtype-def {and classtype-def}`

`classtype-def ::= [virtual] [[type-parameters]] class-name = class-body-type`

A class type definition `class class-name = class-body-type` defines an abbreviation `class-name` for the class body type `class-body-type`. As for class definitions, two type abbreviations `class-name` and `# class-name` are also defined. The definition can be parameterized by some type parameters. If any method in the class type body is virtual, the definition must be flagged `virtual`.

Two class type definitions match if they have the same type parameters and they expand to matching types.

## 11.10 Module types (module specifications)

Module types are the module-level equivalent of type expressions: they specify the general shape and type properties of modules.
## Module specifications

A specification of a module component in a signature is written `module module-name : module-type`, where `module-name` is the name of the module component and `module-type` its expected type. Modules can be nested arbitrarily; in particular, functors can appear as components of structures and functor types as components of signatures.

For specifying a module component that is a functor, one may write

`module module-name ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) : module-type`

instead of

`module module-name : functor ( name₁ : module-type₁ ) -> ... -> module-type`

## Module type specifications

A module type component of a signature can be specified either as a manifest module type or as an abstract module type.

An abstract module type specification `module type modtype-name` allows the name `modtype-name` to be implemented by any module type in a matching signature, but hides the implementation of the module type to all users of the signature.

A manifest module type specification `module type modtype-name = module-type` requires the name `modtype-name` to be implemented by the module type `module-type` in a matching signature, but makes the equality between `modtype-name` and `module-type` apparent to all users of the signature.

### 11.10.3 Opening a module path

The expression `open module-path` in a signature does not specify any components. It simply affects the parsing of the following items of the signature, allowing components of the module denoted by `module-path` to be referred to by their simple names `name` instead of path accesses `module-path`. `name`. The scope of the `open` stops at the end of the signature expression.

### 11.10.4 Including a signature

The expression `include module-type` in a signature performs textual inclusion of the components of the signature denoted by `module-type`. It behaves as if the components of the included signature were copied at the location of the `include`. The `module-type` argument must refer to a module type that is a signature, not a functor type.

### 11.10.5Functor types

The module type expression `functor ( module-name : module-type₁ ) -> module-type₂` is the type of functors (functions from modules to modules) that take as argument a module of type `module-type₁` and return as result a module of type `module-type₂`. The module type `module-type₂` can use the name `module-name` to refer to type components of the actual argument of the functor. If the type `module-type₂` does not depend on type components of `module-name`, the module type expression can be simplified with the alternative short syntax `module-type₁ -> module-type₂`. No
module-type ::= modtype-path
| sig {specification [;;]} end
| [functor] { ( module-name : module-type ) }⁺ -> module-type
| module-type -> module-type
| module-type with mod-constraint { and mod-constraint }
| ( module-type )

mod-constraint ::= type [type-params] typeconstr type-equation {type-constraint}
| module module-path = extended-module-path

specification ::= val value-name : typexpr
| external value-name : typexpr = external-declaration
| type-definition
| exception constr-decl
| class-specification
| classtype-definition
| module module-name : module-type
| module module-name { ( module-name : module-type ) } : module-type
| module type modtype-name
| module type modtype-name = module-type
| open module-path
| include module-type

See also the following language extensions: recovering the type of a module, substitution inside a signature, type-level module aliases, attributes, extension nodes, generative functors, and module type substitutions.

11.10.1 Simple module types

The expression *modtype-path* is equivalent to the module type bound to the name *modtype-path*.

The expression `( module-type )` denotes the same type as *module-type*.

11.10.2 Signatures

Signatures are type specifications for structures. Signatures sig...end are collections of type specifications for value names, type names, exceptions, module names and module type names. A structure will match a signature if the structure provides definitions (implementations) for all the names specified in the signature (and possibly more), and these definitions meet the type requirements given in the signature.

An optional ;; is allowed after each specification in a signature. It serves as a syntactic separator with no semantic meaning.
restrictions are placed on the type of the functor argument; in particular, a functor may take another
functor as argument ("higher-order" functor).

When the result module type is itself a functor,

`functor ( name₁ : module-type₁ ) -> ... -> functor ( nameₙ : module-typeₙ ) -> module-type`

one may use the abbreviated form

`functor ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) -> module-type`

11.10.6 The with operator

Assuming *module-type* denotes a signature, the expression *module-type* with *mod-constraint*
{and *mod-constraint*} denotes the same signature where type equations have been added to some
of the type specifications, as described by the constraints following the *with* keyword. The
constraint *type* [*type-parameters*] *typeconstr* = *typexpr* adds the type equation = *typexpr* to the
specification of the type component named *typeconstr* of the constrained signature. The constraint
*module module-path* = *extended-module-path* adds type equations to all type components of the sub-
structure denoted by *module-path*, making them equivalent to the corresponding type components
of the structure denoted by *extended-module-path*.

For instance, if the module type name S is bound to the signature

sig type t module M: (sig type u end) end

then S with type t=int denotes the signature

sig type t=int module M: (sig type u end) end

and S with module M = N denotes the signature

sig type t module M: (sig type u=N.u end) end

A functor taking two arguments of type S that share their t component is written

functor (A: S) (B: S with type t = A.t) ...

Constraints are added left to right. After each constraint has been applied, the resulting signature must be a subtype of the signature before the constraint was applied. Thus, the `with` operator can only add information on the type components of a signature, but never remove information.

11.11 Module expressions (module implementations)

Module expressions are the module-level equivalent of value expressions: they evaluate to modules,
thus providing implementations for the specifications expressed in module types.
## Value specifications

A specification of a value component in a signature is written `val value-name : typexpr`, where `value-name` is the name of the value and `typexpr` its expected type.

The form `external value-name : typexpr = external-declaration` is similar, except that it requires in addition the name to be implemented as the external function specified in `external-declaration` (see chapter 22).

## Type specifications

A specification of one or several type components in a signature is written `type typedef {and typedef}` and consists of a sequence of mutually recursive definitions of type names.

Each type definition in the signature specifies an optional type equation `= typexpr` and an optional type representation `= constr-decl...` or `= { field-decl... }`. The implementation of the type name in a matching structure must be compatible with the type expression specified in the equation (if given), and have the specified representation (if given). Conversely, users of that signature will be able to rely on the type equation or type representation, if given. More precisely, we have the following four situations:

### Abstract type: no equation, no representation.

Names that are defined as abstract types in a signature can be implemented in a matching structure by any kind of type definition (provided it has the same number of type parameters). The exact implementation of the type will be hidden to the users of the structure. In particular, if the type is implemented as a variant type or record type, the associated constructors and fields will not be accessible to the users; if the type is implemented as an abbreviation, the type equality between the type name and the right-hand side of the abbreviation will be hidden from the users of the structure. Users of the structure consider that type as incompatible with any other type: a fresh type has been generated.

### Type abbreviation: an equation = typexpr, no representation.

The type name must be implemented by a type compatible with `typexpr`. All users of the structure know that the type name is compatible with `typexpr`.

### New variant type or record type: no equation, a representation.

The type name must be implemented by a variant type or record type with exactly the constructors or fields specified. All users of the structure have access to the constructors or fields, and can use them to create or inspect values of that type. However, users of the structure consider that type as incompatible with any other type: a fresh type has been generated.

### Re-exported variant type or record type: an equation, a representation.

This case combines the previous two: the representation of the type is made visible to all users, and no fresh type is generated.

## Exception specification

The specification `exception constr-decl` in a signature requires the matching structure to provide an exception with the name and arguments specified in the definition, and makes the exception
module-expr ::= module-path
                  | struct [module-items] end
                  | functor ( module-name : module-type ) -> module-expr
                  | module-expr ( module-expr )
                  | ( module-expr )
                  | ( module-expr : module-type )

module-items ::= {;;} (definition | expr) {{;;} (definition | ;; expr)} {;;}

definition ::= let [rec] let-binding {and let-binding}
               | external value-name : typexpr = external-declaration
               | type-definition
               | exception-definition
               | class-definition
               | classtype-definition
               | module module-name { ( module-name : module-type ) } [ : module-type ]
                   = module-expr
               | module type modtype-name = module-type
               | open module-path
               | include module-expr

See also the following language extensions: recursive modules, first-class modules, overriding in open statements, attributes, extension nodes and generative functors.

### 11.11.1 Simple module expressions

The expression `module-path` evaluates to the module bound to the name `module-path`.

The expression `( module-expr )` evaluates to the same module as `module-expr`.

The expression `( module-expr : module-type )` checks that the type of `module-expr` is a subtype of `module-type`, that is, that all components specified in `module-type` are implemented in `module-expr`, and their implementation meets the requirements given in `module-type`. In other terms, it checks that the implementation `module-expr` meets the type specification `module-type`. The whole expression evaluates to the same module as `module-expr`, except that all components not specified in `module-type` are hidden and can no longer be accessed.

### 11.11.2 Structures

Structures `struct...end` are collections of definitions for value names, type names, exceptions, module names and module type names. The definitions are evaluated in the order in which they appear in the structure. The scopes of the bindings performed by the definitions extend to the end of the structure. As a consequence, a definition may refer to names bound by earlier definitions in the same structure.

For compatibility with toplevel phrases (chapter 14), optional `;;` are allowed after and before each definition in a structure. These `;;` have no semantic meanings. Similarly, an `expr` preceded by `;;` is allowed as a component of a structure. It is equivalent to `let_ = expr`, i.e. `expr` is evaluated
available to all users of the structure.

### Class specifications

A specification of one or several classes in a signature is written `class class-spec {and class-spec}` and consists of a sequence of mutually recursive definitions of class names.

Class specifications are described more precisely in section 11.9.4.

### Class type specifications

A specification of one or several class types in a signature is written `class type classtype-def {and classtype-def}` and consists of a sequence of mutually recursive definitions of class type names. Class type specifications are described more precisely in section 11.9.5.

### Module specifications

A specification of a module component in a signature is written `module module-name : module-type`, where `module-name` is the name of the module component and `module-type` its expected type. Modules can be nested arbitrarily; in particular, functors can appear as components of structures and functor types as components of signatures.

For specifying a module component that is a functor, one may write

`module module-name ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) : module-type`

instead of

`module module-name : ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) -> module-type`

### Module type specifications

A module type component of a signature can be specified either as a manifest module type or as an abstract module type.

An abstract module type specification `module type modtype-name` allows the name `modtype-name` to be implemented by any module type in a matching signature, but hides the implementation of the module type to all users of the signature.

A manifest module type specification `module type modtype-name = module-type` requires the name `modtype-name` to be implemented by the module type `module-type` in a matching signature, but makes the equality between `modtype-name` and `module-type` apparent to all users of the signature.

### 11.10.3 Opening a module path

The expression `open module-path` in a signature does not specify any components. It simply affects the parsing of the following items of the signature, allowing components of the module denoted by `module-path` to be referred to by their simple names `name` instead of path accesses `module-path`. `name`. The scope of the `open` stops at the end of the signature expression.
for its side-effects but is not bound to any identifier. If `expr` is the first component of a structure, the preceding `;;` can be omitted.

## Value definitions

A value definition `let [rec] let-binding {and let-binding}` bind value names in the same way as a `let...in...` expression (see section 11.7.2). The value names appearing in the left-hand sides of the bindings are bound to the corresponding values in the right-hand sides.

A value definition `external value-name : typexpr = external-declaration` implements `value-name` as the external function specified in `external-declaration` (see chapter 22).

## Type definitions

A definition of one or several type components is written `type typedef {and typedef}` and consists of a sequence of mutually recursive definitions of type names.

## Exception definitions

Exceptions are defined with the syntax `exception constr-decl` or `exception constr-name = constr`.

## Class definitions

A definition of one or several classes is written `class class-binding {and class-binding}` and consists of a sequence of mutually recursive definitions of class names. Class definitions are described more precisely in section 11.9.3.

## Class type definitions

A definition of one or several classes is written `class type classtype-def {and classtype-def}` and consists of a sequence of mutually recursive definitions of class type names. Class type definitions are described more precisely in section 11.9.5.

## Module definitions

The basic form for defining a module component is `module module-name = module-expr`, which evaluates `module-expr` and binds the result to the name `module-name`.

One can write

`module module-name : module-type = module-expr`

instead of

`module module-name = ( module-expr : module-type ).`

Another derived form is

`module module-name ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) = module-expr`

which is equivalent to

`module module-name = functor ( name₁ : module-type₁ ) -> ... -> module-expr`
### 11.10.4 Including a signature

The expression `include module-type` in a signature performs textual inclusion of the components of the signature denoted by `module-type`. It behaves as if the components of the included signature were copied at the location of the `include`. The `module-type` argument must refer to a module type that is a signature, not a functor type.

### 11.10.5 functor types

The module type expression `[functor] ( module-name : module-type₁ ) -> module-type₂` is the type of functors (functions from modules to modules) that take as argument a module of type `module-type₁` and return as result a module of type `module-type₂`. The module type `module-type₂` can use the name `module-name` to refer to type components of the actual argument of the functor. If the type `module-type₂` does not depend on type components of `module-name`, the module type expression can be simplified with the alternative short syntax `module-type₁ -> module-type₂`. No restrictions are placed on the type of the functor argument; in particular, a functor may take another functor as argument ("higher-order" functor).

When the result module type is itself a functor,

( name₁ : module-type₁ ) -> ... -> ( nameₙ : module-typeₙ ) -> module-type

one may use the abbreviated form

( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) -> module-type

### 11.10.6 The with operator

Assuming `module-type` denotes a signature, the expression `module-type with mod-constraint {and mod-constraint}` denotes the same signature where type equations have been added to some of the type specifications, as described by the constraints following the `with` keyword. The constraint `type [type-parameters] typeconstr = typexpr` adds the type equation `= typexpr` to the specification of the type component named `typeconstr` of the constrained signature. The constraint `module module-path = extended-module-path` adds type equations to all type components of the sub-structure denoted by `module-path`, making them equivalent to the corresponding type components of the structure denoted by `extended-module-path`.

For instance, if the module type name `S` is bound to the signature

sig type t module M: (sig type u end) end

then `S with type t=int` denotes the signature

sig type t=int module M: (sig type u end) end

and `S with module M = N` denotes the signature

sig type t module M: (sig type u=N.u end) end

A functor taking two arguments of type `S` that share their `t` component is written

functor (A: S) (B: S with type t = A.t) ...

Constraints are added left to right. After each constraint has been applied, the resulting signature must be a subtype of the signature before the constraint was applied. Thus, the `with` operator can only add information on the type components of a signature, but never remove information.
## Module type definitions

A definition for a module type is written `module type modtype-name = module-type`. It binds the name `modtype-name` to the module type denoted by the expression `module-type`.

## Opening a module path

The expression `open module-path` in a structure does not define any components nor perform any bindings. It simply affects the parsing of the following items of the structure, allowing components of the module denoted by `module-path` to be referred to by their simple names `name` instead of path accesses `module-path`. `name`. The scope of the `open` stops at the end of the structure expression.

## Including the components of another structure

The expression `include module-expr` in a structure re-exports in the current structure all definitions of the structure denoted by `module-expr`. For instance, if you define a module `S` as below

```hhl
module S = struct type t = int let x = 2 end
```
defining the module `B` as

```hhl
module B = struct include S let y = (x + 1 : t) end
```
is equivalent to defining it as

```hhl
module B = struct type t = S.t let x = S.x let y = (x + 1 : t) end
```

The difference between `open` and `include` is that `open` simply provides short names for the components of the opened structure, without defining any components of the current structure, while `include` also adds definitions for the components of the included structure.

### 11.11.3 Functors

####Functor definition

The expression `functor ( module-name : module-type ) -> module-expr` evaluates to a functor that takes as argument modules of the type `module-type₁`, binds `module-name` to these modules, evaluates `module-expr` in the extended environment, and returns the resulting modules as results. No restrictions are placed on the type of the functor argument; in particular, a functor may take another functor as argument (“higher-order” functor).

When the result module expression is itself a functor,

```
functor ( name₁ : module-type₁ ) -> ... -> functor ( nameₙ : module-typeₙ ) -> module-expr
```

one may use the abbreviated form

```
functor ( name₁ : module-type₁ ) ... ( nameₙ : module-typeₙ ) -> module-expr
```

####Functor application

The expression `module-expr₁ ( module-expr₂ )` evaluates `module-expr₁` to a functor and `module-expr₂` to a module, and applies the former to the latter. The type of `module-expr₂` must match the type expected for the arguments of the functor `module-expr₁`.
## 11.11 Module expressions (module implementations)

Module expressions are the module-level equivalent of value expressions: they evaluate to modules, thus providing implementations for the specifications expressed in module types.

module-expr ::= module-path
                  struct [module-items] end
                  functor {(module-name : module-type)}⁺ -> module-expr
                  module-expr (module-expr)
                  (module-expr)
                  (module-expr : module-type)

module-items ::= {;;} (definition | expr) {{;;} (definition | ;; expr)} {;;}

definition ::= let [rec] let-binding {and let-binding}
                  external value-name : typexpr = external-declaration
                  type-definition
                  exception-definition
                  class-definition
                  classtype-definition
                  module module-name {(module-name : module-type)} [: module-type]
                  = module-expr
                  module type modtype-name = module-type
                  open module-path
                  include module-expr

See also the following language extensions: recursive modules, first-class modules, overriding in open statements, attributes, extension nodes and generative functors.

### 11.11.1 Simple module expressions

The expression *module-path* evaluates to the module bound to the name *module-path*.

The expression (*module-expr*) evaluates to the same module as *module-expr*.

The expression (*module-expr* : *module-type*) checks that the type of *module-expr* is a subtype of *module-type*, that is, that all components specified in *module-type* are implemented in *module-expr*, and their implementation meets the requirements given in *module-type*. In other terms, it checks that the implementation *module-expr* meets the type specification *module-type*. The whole expression evaluates to the same module as *module-expr*, except that all components not specified in *module-type* are hidden and can no longer be accessed.

### 11.11.2 Structures

Structures `struct...end` are collections of definitions for value names, type names, exceptions, module names and module type names. The definitions are evaluated in the order in which they appear in the structure. The scopes of the bindings performed by the definitions extend to the end of the structure. As a consequence, a definition may refer to names bound by earlier definitions in the same structure.
## 11.12 Compilation units

$$ \mathit{unit-interface} ::= \{\mathit{specification} [;;]\} $$

$$ \mathit{unit-implementation} ::= [\mathit{module-items}] $$

Compilation units bridge the module system and the separate compilation system. A compilation unit is composed of two parts: an interface and an implementation. The interface contains a sequence of specifications, just as the inside of a `sig...end` signature expression. The implementation contains a sequence of definitions and expressions, just as the inside of a `struct...end` module expression. A compilation unit also has a name `unit-name`, derived from the names of the files containing the interface and the implementation (see chapter 13 for more details). A compilation unit behaves roughly as the module definition

$$ \mathbf{module} \mathit{unit-name} : \mathit{sig} \mathit{unit-interface} \mathit{end} = \mathbf{struct} \mathit{unit-implementation} \mathit{end} $$

A compilation unit can refer to other compilation units by their names, as if they were regular modules. For instance, if `U` is a compilation unit that defines a type `t`, other compilation units can refer to that type under the name `U.t`; they can also refer to `U` as a whole structure. Except for names of other compilation units, a unit interface or unit implementation must not have any other free variables. In other terms, the type-checking and compilation of an interface or implementation proceeds in the initial environment

$$ \mathit{name}_1 : \mathit{sig} \mathit{specification}_1 \mathit{end} \dots \mathit{name}_n : \mathit{sig} \mathit{specification}_n \mathit{end} $$

where `name_1...name_n` are the names of the other compilation units available in the search path (see chapter 13 for more details) and `specification_1...specification_n` are their respective interfaces.
For compatibility with toplevel phrases (chapter 14), optional `;;` are allowed after and before each definition in a structure. These `;;` have no semantic meanings. Similarly, an `expr` preceded by `;;` is allowed as a component of a structure. It is equivalent to `let_ = expr`, i.e. `expr` is evaluated for its side-effects but is not bound to any identifier. If `expr` is the first component of a structure, the preceding `;;` can be omitted.

## Value definitions

A value definition `let [rec] let-binding {and let-binding}` bind value names in the same way as a `let...in...` expression (see section 11.7.2). The value names appearing in the left-hand sides of the bindings are bound to the corresponding values in the right-hand sides.

A value definition `external value-name : typexpr = external-declaration` implements `value-name` as the external function specified in `external-declaration` (see chapter 22).

## Type definitions

A definition of one or several type components is written `type typedef {and typedef}` and consists of a sequence of mutually recursive definitions of type names.

## Exception definitions

Exceptions are defined with the syntax `exception constr-decl` or `exception constr-name = constr`.

## Class definitions

A definition of one or several classes is written `class class-binding {and class-binding}` and consists of a sequence of mutually recursive definitions of class names. Class definitions are described more precisely in section 11.9.3.

## Class type definitions

A definition of one or several classes is written `class type classtype-def {and classtype-def}` and consists of a sequence of mutually recursive definitions of class type names. Class type definitions are described more precisely in section 11.9.5.

## Module definitions

The basic form for defining a module component is `module module-name = module-expr`, which evaluates `module-expr` and binds the result to the name `module-name`.

One can write

`module module-name : module-type = module-expr`

instead of

`module module-name = ( module-expr : module-type ).`

Another derived form is