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

which is equivalent to

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

## 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

`module S = struct type t = int let x = 2 end`

defining the module `B` as

`module B = struct include S let y = (x + 1 : t) end`

is equivalent to defining it as

`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`
# Chapter 12

## Language extensions

This chapter describes language extensions and convenience features that are implemented in OCaml, but not described in chapter 11.

### 12.1 Recursive definitions of values

(Introduced in Objective Caml 1.00)

As mentioned in section 11.7.2, the `let rec` binding construct, in addition to the definition of recursive functions, also supports a certain class of recursive definitions of non-functional values, such as

`let rec name₁ = 1 :: name₂ and name₂ = 2 :: name₁ in expr`

which binds `name₁` to the cyclic list `1::2::1::2::...`, and `name₂` to the cyclic list `2::1::2::1::...`. Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.

More precisely, consider the expression:

`let rec name₁ = expr₁ and ... and nameₙ = exprₙ in expr`

It will be accepted if each one of `expr₁...exprₙ` is statically constructive with respect to `name₁...nameₙ`, is not immediately linked to any of `name₁...nameₙ`, and is not an array constructor whose arguments have abstract type.

An expression `e` is said to be *statically constructive with respect to* the variables `name₁...nameₙ` if at least one of the following conditions is true:

* `e` has no free occurrence of any of `name₁...nameₙ`

* `e` is a variable

* `e` has the form `fun...->...`

* `e` has the form `function...->...`

* `e` has the form `lazy (...)`
## 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.12 Compilation units

`unit-interface ::= {specification [;;]}`

`unit-implementation ::= [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

`module unit-name : sig unit-interface end = struct unit-implementation 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

`name₁ : sig specification₁ end...nameₙ : sig specificationₙ end`

where `name₁...nameₙ` are the names of the other compilation units available in the search path (see chapter 13 for more details) and `specification₁...specificationₙ` are their respective interfaces.
* `e` has one of the following forms, where each one of `expr1...exprm` is statically constructive with respect to `name1...name_n`, and `expr0` is statically constructive with respect to `name1...name_n`, `xname1...xname_m`:

- `let [rec] xname1 = expr1 and...and xname m = expr m in expr 0`

- `let module...in expr1`

- `constr ( expr1 , ..., expr m )`

- `tag-name ( expr1 , ..., expr m )`

- `[ expr1 ; ... ; expr m ]`

- `{ field1 = expr1 ; ... ; field m = expr m }`

- `{ expr1 with field2 = expr2 ; ... ; field m = expr m }` where `expr1` is not immediately linked to `name1...name_n`

- `( expr1 , ..., expr m )`

- `expr1 ; ... ; expr m`

An expression `e` is said to be *immediately linked to* the variable *name* in the following cases:

* `e` is *name*

* `e` has the form `expr1 ; ... ; exprm` where `exprm` is immediately linked to *name*

* `e` has the form `let [rec] xname1 = expr1 and...and xname m = expr m in expr 0` where `expr 0` is immediately linked to *name* or to one of the `xnamei` such that `expri` is immediately linked to *name*.

## 12.2 Recursive modules

(Introduced in Objective Caml 3.07)

definition ::= ...
| module rec module-name : module-type = module-expr
  {and module-name : module-type = module-expr}

specification ::= ...
| module rec module-name : module-type {and module-name : module-type}

Recursive module definitions, introduced by the `module rec ... and ...` construction, generalize regular module definitions `module module-name = module-expr` and module specifications `module module-name : module-type` by allowing the defining `module-expr` and the `module-type` to refer recursively to the module identifiers being defined. A typical example of a recursive module definition is:

module rec A : sig
type t = Leaf of string | Node of ASet.t
val compare: t -> t -> int
```h
end = struct
    type t = Leaf of string | Node of ASet.t
let compare t1 t2 =
    match (t1, t2) with
    | (Leaf s1, Leaf s2) -> Stdlib compares1 s2
    | (Leaf_, Node_) -> 1
    | (Node_, Leaf_) -> -1
    | (Node n1, Node n2) -> ASet compare n1 n2
```

end

and ASet
: Set.S with type elt = A.t
= Set.Make(A)

It can be given the following specification:

```h
module rec A : sig
    type t = Leaf of string | Node of ASet.t
    val compare: t -> t -> int
end
and ASet : Set.S with type elt = A.t
```

This is an experimental extension of OCaml: the class of recursive definitions accepted, as well as its dynamic semantics are not final and subject to change in future releases.

Currently, the compiler requires that all dependency cycles between the recursively-defined module identifiers go through at least one "safe" module. A module is "safe" if all value definitions that it contains have function types `typexpr₁ -> typexpr₂`. Evaluation of a recursive module definition proceeds by building initial values for the safe modules involved, binding all (functional) values to `fun _ -> raiseUndefined_recursive_module`. The defining module expressions are then evaluated, and the initial values for the safe modules are replaced by the values thus computed. If a function component of a safe module is applied during this computation (which corresponds to an ill-founded recursive definition), the `Undefined_recursive_module` exception is raised at runtime:

```h
module rec M: sig val f: unit -> int end = struct let f () = N.x end
and N:sig val x: int end = struct let x = M.f () end
Exception:
Undefined_recursive_module ("extensions/recursivemodules.etex", 1, 43).
```

If there are no safe modules along a dependency cycle, an error is raised

```h
module rec M: sig val x: int end = struct let x = N.y end
and N:sig val x: int val y:int end = struct let x = M.x let y = 0 end
```

```
Error: Cannot safely evaluate the definition of the following cycle
of recursively-defined modules: M -> N -> M.
There are no safe modules in this cycle (see manual section 12.2).
Module M defines an unsafe value, x .
Module N defines an unsafe value, x .
```

Note that, in the specification case, the module-types must be parenthesized if they use the `with mod-constraint` construct.
# Chapter 12

## Language extensions

This chapter describes language extensions and convenience features that are implemented in OCaml, but not described in chapter 11.

### 12.1 Recursive definitions of values

(Introduced in Objective Caml 1.00)

As mentioned in section 11.7.2, the `let rec` binding construct, in addition to the definition of recursive functions, also supports a certain class of recursive definitions of non-functional values, such as

`let rec name₁ = 1 :: name₂ and name₂ = 2 :: name₁ in expr`

which binds `name₁` to the cyclic list `1::2::1::2::...`, and `name₂` to the cyclic list `2::1::2::1::...`. Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.

More precisely, consider the expression:

`let rec name₁ = expr₁ and ... and nameₙ = exprₙ in expr`

It will be accepted if each one of `expr₁...exprₙ` is statically constructive with respect to `name₁...nameₙ`, is not immediately linked to any of `name₁...nameₙ`, and is not an array constructor whose arguments have abstract type.

An expression `e` is said to be *statically constructive with respect to* the variables `name₁...nameₙ` if at least one of the following conditions is true:

* `e` has no free occurrence of any of `name₁...nameₙ`

* `e` is a variable

* `e` has the form `fun...->...`

* `e` has the form `function...->...`

* `e` has the form `lazy (...)`
## 12.3 Private types

Private type declarations in module signatures, of the form `type t = private ...`, enable libraries to reveal some, but not all aspects of the implementation of a type to clients of the library. In this respect, they strike a middle ground between abstract type declarations, where no information is revealed on the type implementation, and data type definitions and type abbreviations, where all aspects of the type implementation are publicized. Private type declarations come in three flavors: for variant and record types (section 12.3.1), for type abbreviations (section 12.3.2), and for row types (section 12.3.3).

### 12.3.1 Private variant and record types

(Introduced in Objective Caml 3.07)

$$ \begin{array}{l} \texttt{type-representation ::= ...} \\ \quad = \texttt{private} [l] \texttt{constr-decl} \{ \texttt{constr-decl}\} \\ \quad = \texttt{private record-decl} \end{array} $$

Values of a variant or record type declared `private` can be de-structured normally in pattern-matching or via the `expr . field` notation for record accesses. However, values of these types cannot be constructed directly by constructor application or record construction. Moreover, assignment on a mutable field of a private record type is not allowed.

The typical use of private types is in the export signature of a module, to ensure that construction of values of the private type always go through the functions provided by the module, while still allowing pattern-matching outside the defining module. For example:

```ocaml
module M : sig
    type t = private A | B of int
    val a : t
    val b : int -> t
end = struct
    type t = A | B of int
    let a = A
    let b n = assert (n > 0); B n
end
```

Here, the `private` declaration ensures that in any value of type `M.t`, the argument to the `B` constructor is always a positive integer.

With respect to the variance of their parameters, private types are handled like abstract types. That is, if a private type has parameters, their variance is the one explicitly given by prefixing the parameter by a `+` or a `-`, it is invariant otherwise.

### 12.3.2 Private type abbreviations

(Introduced in Objective Caml 3.11)

$$ \begin{array}{l} \texttt{type-equation ::= ...} \\ \quad = \texttt{private typexpr} \end{array} $$
* e has one of the following forms, where each one of `expr_1...expr_m` is statically constructive with respect to `name_1...name_n`, and `expr_0` is statically constructive with respect to `name_1...name_n`, `xname_1...xname_m`:

- `let [rec] xname_1 = expr_1 and...and xname_m = expr_m in expr_0`

- `let module...in expr_1`

- `constr ( expr_1 , ..., expr_m )`

- `tag-name ( expr_1 , ..., expr_m )`

- `[ expr_1 ; ... ; expr_m ]`

- `{ field_1 = expr_1 ; ... ; field_m = expr_m }`

- `{ expr_1 with field_2 = expr_2 ; ... ; field_m = expr_m }` where `expr_1` is not immediately linked to `name_1...name_n`

- `( expr_1 , ..., expr_m )`

- `expr_1 ; ... ; expr_m`

An expression `e` is said to be *immediately linked to* the variable `name` in the following cases:

* `e` is `name`

* `e` has the form `expr_1 ; ... ; expr_m` where `expr_m` is immediately linked to `name`

* `e` has the form `let [rec] xname_1 = expr_1 and...and xname_m = expr_m in expr_0` where `expr_0` is immediately linked to `name` or to one of the `xname_i` such that `expr_i` is immediately linked to `name`.

## 12.2 Recursive modules

(Introduced in Objective Caml 3.07)

definition ::= ...
| module rec module-name : module-type = module-expr
  {and module-name : module-type = module-expr}

specification ::= ...
| module rec module-name : module-type {and module-name : module-type}

Recursive module definitions, introduced by the `module rec ...and ...` construction, generalize regular module definitions `module module-name = module-expr` and module specifications `module module-name : module-type` by allowing the defining `module-expr` and the `module-type` to refer recursively to the module identifiers being defined. A typical example of a recursive module definition is:

module rec A : sig
type t = Leaf of string | Node of ASet.t
val compare: t -> t -> int
Unlike a regular type abbreviation, a private type abbreviation declares a type that is distinct from its implementation type *typexpr*. However, coercions from the type to *typexpr* are permitted. Moreover, the compiler “knows” the implementation type and can take advantage of this knowledge to perform type-directed optimizations.

The following example uses a private type abbreviation to define a module of nonnegative integers:

```python
module N : sig
type t = private int
val of_int: int -> t
val to_int: t -> int
end = struct
type t = int
let of_int n = assert (n >= 0); n
let to_int n = n
end
```

The type `N.t` is incompatible with `int`, ensuring that nonnegative integers and regular integers are not confused. However, if `x` has type `N.t`, the coercion (`x :> int`) is legal and returns the underlying integer, just like `N.to_int x`. Deep coercions are also supported: if `l` has type `N.t list`, the coercion (`l :> int list`) returns the list of underlying integers, like `List.map N.to_int l` but without copying the list `l`.

Note that the coercion (`expr :> typexpr`) is actually an abbreviated form, and will only work in presence of private abbreviations if neither the type of `expr` nor `typexpr` contain any type variables. If they do, you must use the full form (`expr : typexpr₁ :> typexpr₂`) where `typexpr₁` is the expected type of `expr`. Concretely, this would be (`x : N.t :> int`) and (`l : N.t list :> int list`) for the above examples.

### 12.3.3 Private row types

(Introduced in Objective Caml 3.09)

```
type-equation ::= ...
| = private typexpr
```

Private row types are type abbreviations where part of the structure of the type is left abstract. Concretely `typexpr` in the above should denote either an object type or a polymorphic variant type, with some possibility of refinement left. If the private declaration is used in an interface, the corresponding implementation may either provide a ground instance, or a refined private type.

```python
module M : sig type c = private < x : int; .. > val o : c end =
struct
class c = object method x = 3 method y = 2 end
let o = new c
end
```

This declaration does more than hiding the `y` method, it also makes the type `c` incompatible with any other closed object type, meaning that only `o` will be of type `c`. In that respect it behaves similarly to private record types. But private row types are more flexible with respect to incremental refinement. This feature can be used in combination with functors.
```h
end = struct
    type t = Leaf of string | Node of ASet.t
let compare t1 t2 =
    match (t1, t2) with
    | (Leaf s1, Leaf s2) -> Stdlib compare s1 s2
    | (Leaf_, Node_) -> 1
    | (Node_, Leaf_) -> -1
    | (Node n1, Node n2) -> ASet compare n1 n2
end
```

```h
end
and ASet
    : Set.S with type elt = A.t
    = Set.Make(A)
```

It can be given the following specification:

```h
module rec A : sig
    type t = Leaf of string | Node of ASet.t
    val compare: t -> t -> int
end
and ASet : Set.S with type elt = A.t
```

This is an experimental extension of OCaml: the class of recursive definitions accepted, as well as its dynamic semantics are not final and subject to change in future releases.

Currently, the compiler requires that all dependency cycles between the recursively-defined module identifiers go through at least one "safe" module. A module is "safe" if all value definitions that it contains have function types `typexpr₁ -> typexpr₂`. Evaluation of a recursive module definition proceeds by building initial values for the safe modules involved, binding all (functional) values to `fun _ -> raiseUndefined_recursive_module`. The defining module expressions are then evaluated, and the initial values for the safe modules are replaced by the values thus computed. If a function component of a safe module is applied during this computation (which corresponds to an ill-founded recursive definition), the `Undefined_recursive_module` exception is raised at runtime:

```h
module rec M: sig val f: unit -> int end = struct let f () = N.x end
and N:sig val x: int end = struct let x = M.f () end
Exception:
Undefined_recursive_module ("extensions/recursivemodules.etex", 1, 43).
```

If there are no safe modules along a dependency cycle, an error is raised

```h
module rec M: sig val x: int end = struct let x = N.y end
and N:sig val x: int val y:int end = struct let x = M.x let y = 0 end
```

```
Error: Cannot safely evaluate the definition of the following cycle
    of recursively-defined modules: M -> N -> M.
    There are no safe modules in this cycle (see manual section 12.2).
Module M defines an unsafe value, x .
Module N defines an unsafe value, x .
```

Note that, in the specification case, the module-types must be parenthesized if they use the `with mod-constraint` construct.
module F(X : sig type c = private < x : int; .. > end) =
struct

let get_x (o : X.c) = o#x

end

module G(X : sig type c = private < x : int; y : int; .. > end) =
struct

include F(X)

let get_y (o : X.c) = o#y

end

A polymorphic variant type [t], for example

type t = [ `A of int | `B of bool ]

can be refined in two ways. A definition [u] may add new field to [t], and the declaration

type u = private [> t]

will keep those new fields abstract. Construction of values of type [u] is possible using the known variants of [t], but any pattern-matching will require a default case to handle the potential extra fields. Dually, a declaration [u] may restrict the fields of [t] through abstraction: the declaration

type v = private [< t > `A]

corresponds to private variant types. One cannot create a value of the private type [v], except using the constructors that are explicitly listed as present, (`A n`) in this example; yet, when pattern-matching on a `[v]`, one should assume that any of the constructors of `[t]` could be present.

Similarly to abstract types, the variance of type parameters is not inferred, and must be given explicitly.

## 12.4 Locally abstract types

(Introduced in OCaml 3.12, short syntax added in 4.03)

parameter ::= ...
| ( type {typeconstr-name}^ )

The expression `fun ( type typeconstr-name ) -> expr` introduces a type constructor named `typeconstr-name` which is considered abstract in the scope of the sub-expression, but then replaced by a fresh type variable. Note that contrary to what the syntax could suggest, the expression `fun ( type typeconstr-name ) -> expr` itself does not suspend the evaluation of `expr` as a regular abstraction would. The syntax has been chosen to fit nicely in the context of function declarations, where it is generally used. It is possible to freely mix regular function parameters with pseudo type parameters, as in:

let f = fun (type t) (foo : t list) -> ...

and even use the alternative syntax for declaring functions:

let f (type t) (foo : t list) = ...

If several locally abstract types need to be introduced, it is possible to use the syntax `fun ( type typeconstr-name₁...typeconstr-nameₙ ) -> expr` as syntactic sugar for `fun ( type typeconstr-name₁ ) -> ... -> fun ( type typeconstr-nameₙ ) -> expr`. For instance,
## 12.3 Private types

Private type declarations in module signatures, of the form `type t = private ...`, enable libraries to reveal some, but not all aspects of the implementation of a type to clients of the library. In this respect, they strike a middle ground between abstract type declarations, where no information is revealed on the type implementation, and data type definitions and type abbreviations, where all aspects of the type implementation are publicized. Private type declarations come in three flavors: for variant and record types (section 12.3.1), for type abbreviations (section 12.3.2), and for row types (section 12.3.3).

### 12.3.1 Private variant and record types

(Introduced in Objective Caml 3.07)

$$ \begin{array}{l} \texttt{type-representation ::= ...} \\ \quad = \texttt{private} [l] \texttt{constr-decl} \{ \texttt{constr-decl}\} \\ \quad = \texttt{private record-decl} \end{array} $$

Values of a variant or record type declared `private` can be de-structured normally in pattern-matching or via the `expr . field` notation for record accesses. However, values of these types cannot be constructed directly by constructor application or record construction. Moreover, assignment on a mutable field of a private record type is not allowed.

The typical use of private types is in the export signature of a module, to ensure that construction of values of the private type always go through the functions provided by the module, while still allowing pattern-matching outside the defining module. For example:

```ocaml
module M : sig
    type t = private A | B of int
    val a : t
    val b : int -> t
end = struct
    type t = A | B of int
    let a = A
    let b n = assert (n > 0); B n
end
```

Here, the `private` declaration ensures that in any value of type `M.t`, the argument to the `B` constructor is always a positive integer.

With respect to the variance of their parameters, private types are handled like abstract types. That is, if a private type has parameters, their variance is the one explicitly given by prefixing the parameter by a `+` or a `-`, it is invariant otherwise.

### 12.3.2 Private type abbreviations

(Introduced in Objective Caml 3.11)

$$ \begin{array}{l} \texttt{type-equation ::= ...} \\ \quad = \texttt{private typexpr} \end{array} $$
let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> ...
let f' (type t u v) (foo : (t * u * v) list) = ...

This construction is useful because the type constructors it introduces can be used in places where a type variable is not allowed. For instance, one can use it to define an exception in a local module within a polymorphic function.

let f (type t) () =
let module M = struct exception E of t end in
 fun x -> M.E x), (function M.E x -> Some x | _ -> None)

Here is another example:

let sort_uniq (type s) (cmp : s -> s -> int) =
let module S = Set.Make(struct type t = s let compare = cmp end) in
fun l ->
S elements (List.fold_right S.add l S.empty)

It is also extremely useful for first-class modules (see section 12.5) and generalized algebraic datatypes (GADTs: see section 12.10).

Polymorphic syntax (Introduced in OCaml 4.00)

let-binding ::= ...
| value-name : type {typeconstr-name}⁺ . typexpr = expr

class-field ::= ...
| method [private] method-name : type {typeconstr-name}⁺ . typexpr = expr
| method! [private] method-name : type {typeconstr-name}⁺ . typexpr = expr

The (type typeconstr-name) syntax construction by itself does not make polymorphic the type variable it introduces, but it can be combined with explicit polymorphic annotations where needed.
The above rule is provided as syntactic sugar to make this easier:

let rec f : type t1 t2. t1 * t2 list -> t1 = ...
... is automatically expanded into

let rec f : 't1 't2. 't1 * 't2 list -> 't1 =
fun (type t1) (type t2) -> ( ... : t1 * t2 list -> t1)

This syntax can be very useful when defining recursive functions involving GADTs, see the section 12.10 for a more detailed explanation.

The same feature is provided for method definitions.

12.5 First-class modules

(Introduced in OCaml 3.12; pattern syntax and package type inference introduced in 4.00; structural comparison of package types introduced in 4.02.; fewer parens required starting from 4.05)
Unlike a regular type abbreviation, a private type abbreviation declares a type that is distinct from its implementation type `typexpr`. However, coercions from the type to `typexpr` are permitted. Moreover, the compiler “knows” the implementation type and can take advantage of this knowledge to perform type-directed optimizations.

The following example uses a private type abbreviation to define a module of nonnegative integers:

```python
module N : sig
type t = private int
val of_int: int -> t
val to_int: t -> int
end = struct
type t = int
let of_int n = assert (n >= 0); n
let to_int n = n
end
```

The type `N.t` is incompatible with `int`, ensuring that nonnegative integers and regular integers are not confused. However, if `x` has type `N.t`, the coercion (`x :> int`) is legal and returns the underlying integer, just like `N.to_int x`. Deep coercions are also supported: if `l` has type `N.t list`, the coercion (`l :> int list`) returns the list of underlying integers, like `List.map N.to_int l` but without copying the list `l`.

Note that the coercion (`expr :> typexpr`) is actually an abbreviated form, and will only work in presence of private abbreviations if neither the type of `expr` nor `typexpr` contain any type variables. If they do, you must use the full form (`expr : typexpr₁ :> typexpr₂`) where `typexpr₁` is the expected type of `expr`. Concretely, this would be (`x : N.t :> int`) and (`l : N.t list :> int list`) for the above examples.

### 12.3.3 Private row types

(Introduced in Objective Caml 3.09)

```
type-equation ::= ...
| = private typexpr
```

Private row types are type abbreviations where part of the structure of the type is left abstract. Concretely `typexpr` in the above should denote either an object type or a polymorphic variant type, with some possibility of refinement left. If the private declaration is used in an interface, the corresponding implementation may either provide a ground instance, or a refined private type.

```python
module M : sig type c = private < x : int; .. > val o : c end =
struct
class c = object method x = 3 method y = 2 end
let o = new c
end
```

This declaration does more than hiding the `y` method, it also makes the type `c` incompatible with any other closed object type, meaning that only `o` will be of type `c`. In that respect it behaves similarly to private record types. But private row types are more flexible with respect to incremental refinement. This feature can be used in combination with functors.
```
typexpr ::= ...
            | ( module package-type )
```

```
module-expr ::= ...
               | ( val expr [ : package-type ] )
```

```
expr ::= ...
        | ( module module-expr [ : package-type ] )
```

```
pattern ::= ...
            | ( module module-name [ : package-type ] )
```

```
package-type ::= modtype-path
               | modtype-path with package-constraint {and package-constraint}
```

```
package-constraint ::= type typeconstr = typexpr
```

Modules are typically thought of as static components. This extension makes it possible to pack a module as a first-class value, which can later be dynamically unpacked into a module.

The expression `( module module-expr : package-type )` converts the module (structure or functor) denoted by module expression `module-expr` to a value of the core language that encapsulates this module. The type of this core language value is `( module package-type )`. The `package-type` annotation can be omitted if it can be inferred from the context.

Conversely, the module expression `( val expr : package-type )` evaluates the core language expression `expr` to a value, which must have type `module package-type`, and extracts the module that was encapsulated in this value. Again `package-type` can be omitted if the type of `expr` is known. If the module expression is already parenthesized, like the arguments of functors are, no additional parens are needed: `Map.Make(val key)`.

The pattern `( module module-name : package-type )` matches a package with type `package-type` and binds it to `module-name`. It is not allowed in toplevel let bindings. Again `package-type` can be omitted if it can be inferred from the enclosing pattern.

The `package-type` syntactic class appearing in the `( module package-type )` type expression and in the annotated forms represents a subset of module types. This subset consists of named module types with optional constraints of a limited form: only non-parametrized types can be specified.

For type-checking purposes (and starting from OCaml 4.02), package types are compared using the structural comparison of module types.

In general, the module expression `( val expr : package-type )` cannot be used in the body of a functor, because this could cause unsoundness in conjunction with applicative functors. Since OCaml 4.02, this is relaxed in two ways: if `package-type` does not contain nominal type declarations (i.e. types that are created with a proper identity), then this expression can be used anywhere, and even if it contains such types it can be used inside the body of a generative functor, described in section 12.15. It can also be used anywhere in the context of a local module binding `let module module-name = ( val expr_1 : package-type ) in expr_2`.

**Basic example** A typical use of first-class modules is to select at run-time among several implementations of a signature. Each implementation is a structure that we can encapsulate as a
```python
module F(X : sig type c = private < x : int; .. > end) =
struct
```

```python
    let get_x (o : X.c) = o#x
```

```python
end
```

```python
module G(X : sig type c = private < x : int; y : int; .. > end) =
struct
```

```python
    include F(X)
```

```python
    let get_y (o : X.c) = o#y
```

```python
end
```

A polymorphic variant type `[t]`, for example

```python
type t = [ `A of int | `B of bool ]
```

can be refined in two ways. A definition `[u]` may add new field to `[t]`, and the declaration

```python
type u = private [> t]
```

will keep those new fields abstract. Construction of values of type `[u]` is possible using the known variants of `[t]`, but any pattern-matching will require a default case to handle the potential extra fields. Dually, a declaration `[u]` may restrict the fields of `[t]` through abstraction: the declaration

```python
type v = private [< t > `A]
```

corresponds to private variant types. One cannot create a value of the private type `[v]`, except using the constructors that are explicitly listed as present, (`^A n`) in this example; yet, when pattern-matching on a `[v]`, one should assume that any of the constructors of `[t]` could be present.

Similarly to abstract types, the variance of type parameters is not inferred, and must be given explicitly.

## 12.4 Locally abstract types

(Introduced in OCaml 3.12, short syntax added in 4.03)

```python
parameter ::= ...
             | ( type {typeconstr-name}^ )
```

The expression `fun ( type typeconstr-name ) -> expr` introduces a type constructor named `typeconstr-name` which is considered abstract in the scope of the sub-expression, but then replaced by a fresh type variable. Note that contrary to what the syntax could suggest, the expression `fun ( type typeconstr-name ) -> expr` itself does not suspend the evaluation of `expr` as a regular abstraction would. The syntax has been chosen to fit nicely in the context of function declarations, where it is generally used. It is possible to freely mix regular function parameters with pseudo type parameters, as in:

```python
let f = fun (type t) (foo : t list) -> ...
```

and even use the alternative syntax for declaring functions:

```python
let f (type t) (foo : t list) = ...
```

If several locally abstract types need to be introduced, it is possible to use the syntax `fun ( type typeconstr-name₁...typeconstr-nameₙ ) -> expr` as syntactic sugar for `fun ( type typeconstr-name₁ ) -> ... -> fun ( type typeconstr-nameₙ ) -> expr`. For instance,
first-class module, then store in a data structure such as a hash table:

```python
type picture = ...
module type DEVICE = sig
    val draw : picture -> unit
...
end
let devices : (string, (module DEVICE)) Hashtbl.t = Hashtbl.create 17
```

```python
module SVG = struct ... end
let _ = Hashtbl.add devices "SVG" (module SVG : DEVICE)
```

```python
module PDF = struct ... end
let _ = Hashtbl.add devices "PDF" (module PDF : DEVICE)
```

We can then select one implementation based on command-line arguments, for instance:

```python
let parse_cmdline () = ...
module Device =
    (val (let device_name = parse_cmdline () in
        try Hashtbl.find devices device_name
        with Not_found ->
          untf.eprintf "Unknown device %s\n" device_name;
        exit 2)
    : DEVICE)
```

Alternatively, the selection can be performed within a function:

```python
let draw_using_device device_name picture =
    let module Device =
        (val (Hashtbl.find devices device_name) : DEVICE)
    in
    Device.draw picture
```

## Advanced examples
With first-class modules, it is possible to parametrize some code over the implementation of a module without using a functor.

```python
let sort (type s) (module Set : Set.S with type elt = s) l =
    Set (List.fold_right Set.add l Set.empty)
val sort : (module Set.S with type elt = 's) -> 's list -> 's list = <fun>
```

To use this function, one can wrap the `Set.Make` functor:

```python
let make_set (type s) cmp =
    let module S = Set.Make(struct
        type t = s
        let compare = cmp
    end) in
    (module S : Set.S with type elt = s)
val make_set : ('s -> 's -> int) -> (module Set.S with type elt = 's) = <fun>
```
let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> ...
let f' (type t u v) (foo : (t * u * v) list) = ...

This construction is useful because the type constructors it introduces can be used in places where a type variable is not allowed. For instance, one can use it to define an exception in a local module within a polymorphic function.

let f (type t) () =
let module M = struct exception E of t end in
 fun x -> M.E x), (function M.E x -> Some x | _ -> None)

Here is another example:

let sort_uniq (type s) (cmp : s -> s -> int) =
let module S = Set.Make(struct type t = s let compare = cmp end) in
fun l ->
S elements (List.fold_right S. add l S. empty)

It is also extremely useful for first-class modules (see section 12.5) and generalized algebraic datatypes (GADTs: see section 12.10).

**Polymorphic syntax** (Introduced in OCaml 4.00)

let-binding ::= ...
| value-name : type {typeconstr-name}⁺ . typexpr = expr

class-field ::= ...
| method [private] method-name : type {typeconstr-name}⁺ . typexpr = expr
| method! [private] method-name : type {typeconstr-name}⁺ . typexpr = expr

The `(type typeconstr-name)` syntax construction by itself does not make polymorphic the type variable it introduces, but it can be combined with explicit polymorphic annotations where needed. The above rule is provided as syntactic sugar to make this easier:

let rec f : type t1 t2. t1 * t2 list -> t1 = ...
... is automatically expanded into

let rec f : 't1 't2. 't1 * 't2 list -> 't1 =
fun (type t1) (type t2) -> ( ... : t1 * t2 list -> t1)

This syntax can be very useful when defining recursive functions involving GADTs, see the section 12.10 for a more detailed explanation.

The same feature is provided for method definitions.

## 12.5 First-class modules

(Introduced in OCaml 3.12; pattern syntax and package type inference introduced in 4.00; structural comparison of package types introduced in 4.02.; fewer parens required starting from 4.05)
## 12.6 Recovering the type of a module

(Introduced in OCaml 3.12)

$$ \mathit{module-type} ::= \dots \\ | \mathit{module type of} \ \mathit{module-expr} $$

The construction `module type of module-expr` expands to the module type (signature or functor type) inferred for the module expression `module-expr`. To make this module type reusable in many situations, it is intentionally not strengthened: abstract types and datatypes are not explicitly related with the types of the original module. For the same reason, module aliases in the inferred type are expanded.

A typical use, in conjunction with the signature-level `include` construct, is to extend the signature of an existing structure. In that case, one wants to keep the types equal to types in the original module. This can be done using the following idiom.

```sml
module type MYHASH = sig
    include module type of struct include Hashtbl end
    val replace: ('a, 'b) t -> 'a -> 'b -> unit
end
```

The signature `MYHASH` then contains all the fields of the signature of the module `Hashtbl` (with strengthened type definitions), plus the new field `replace`. An implementation of this signature can be obtained easily by using the `include` construct again, but this time at the structure level:

```sml
module MyHash : MYHASH = struct
    include Hashtbl
    let replace t k v = remove t k; add t k v
end
```

Another application where the absence of strengthening comes handy, is to provide an alternative implementation for an existing module.

```sml
module MySet : module type of Set = struct
    ...
end
```

This idiom guarantees that `MySet` is compatible with `Set`, but allows it to represent sets internally in a different way.

## 12.7 Substituting inside a signature

### 12.7.1 Destructive substitutions

(Introduced in OCaml 3.12, generalized in 4.06)

$$ \mathit{mod-constraint} ::= \dots \\ | \mathit{type} \ [\mathit{type-params}] \ \mathit{typeconstr-name} ::= \mathit{typexpr} \\ | \mathit{module} \ \mathit{module-path} ::= \ \mathit{extended-module-path} $$

A “destructive” substitution (`with... := ...`) behaves essentially like normal signature constraints (`with... = ...`), but it additionally removes the redefined type or module from the signature.
```
typexpr ::= ...
             | ( module package-type )
```

```
module-expr ::= ...
               | ( val expr [: package-type] )
```

```
expr ::= ...
        | ( module module-expr [: package-type] )
```

```
pattern ::= ...
            | ( module module-name [: package-type] )
```

```
package-type ::= modtype-path
               | modtype-path with package-constraint {and package-constraint}
```

```
package-constraint ::= type typeconstr = typexpr
```

Modules are typically thought of as static components. This extension makes it possible to pack a module as a first-class value, which can later be dynamically unpacked into a module.

The expression `( module module-expr : package-type )` converts the module (structure or functor) denoted by module expression `module-expr` to a value of the core language that encapsulates this module. The type of this core language value is `( module package-type )`. The `package-type` annotation can be omitted if it can be inferred from the context.

Conversely, the module expression `( val expr : package-type )` evaluates the core language expression `expr` to a value, which must have type `module package-type`, and extracts the module that was encapsulated in this value. Again `package-type` can be omitted if the type of `expr` is known. If the module expression is already parenthesized, like the arguments of functors are, no additional parens are needed: `Map.Make(val key)`.

The pattern `( module module-name : package-type )` matches a package with type `package-type` and binds it to `module-name`. It is not allowed in toplevel let bindings. Again `package-type` can be omitted if it can be inferred from the enclosing pattern.

The `package-type` syntactic class appearing in the `( module package-type )` type expression and in the annotated forms represents a subset of module types. This subset consists of named module types with optional constraints of a limited form: only non-parametrized types can be specified.

For type-checking purposes (and starting from OCaml 4.02), package types are compared using the structural comparison of module types.

In general, the module expression `( val expr : package-type )` cannot be used in the body of a functor, because this could cause unsoundness in conjunction with applicative functors. Since OCaml 4.02, this is relaxed in two ways: if `package-type` does not contain nominal type declarations (i.e. types that are created with a proper identity), then this expression can be used anywhere, and even if it contains such types it can be used inside the body of a generative functor, described in section 12.15. It can also be used anywhere in the context of a local module binding `let module module-name = ( val expr₁ : package-type ) in expr₂`.

**Basic example** A typical use of first-class modules is to select at run-time among several implementations of a signature. Each implementation is a structure that we can encapsulate as a
Prior to OCaml 4.06, there were a number of restrictions: one could only remove types and modules at the outermost level (not inside submodules), and in the case of `with type` the definition had to be another type constructor with the same type parameters.

A natural application of destructive substitution is merging two signatures sharing a type name.

```ocaml
module type Printable = sig
    type t
    val print : Format formatter -> t -> unit
end

module type Comparable = sig
    type t
    val compare : t -> t -> int
end

module type PrintableComparable = sig
    include Printable
    include Comparable with type t := t
end
```

One can also use this to completely remove a field:

```ocaml
module type S = Comparable with type t := int
module type S = sig val compare : int -> int -> int end
```

or to rename one:

```ocaml
module type S = sig
    type u
    include Comparable with type t := u
end

module type S = sig type u val compare : u -> u -> int end
```

Note that you can also remove manifest types, by substituting with the same type.

```ocaml
module type ComparableInt = Comparable with type t = int ;;
module type ComparableInt = sig type t = int val compare : t -> t -> int end
```

```ocaml
module type CompareInt = ComparableInt with type t := int
module type CompareInt = sig val compare : int -> int -> int end
```

## 12.7.2 Local substitution declarations

(Introduced in OCaml 4.08)

```
specification ::= ...
| type type-subst {and type-subst}
| module module-name := extended-module-path
| module type module-name := module-type
type-subst ::= [type-params] typeconstr-name := typexpr {type-constraint}
```
first-class module, then store in a data structure such as a hash table:

```python
type picture = ...
module type DEVICE = sig
    val draw : picture -> unit
...
end
let devices : (string, (module DEVICE)) Hashtbl.t = Hashtbl.create 17
```

```python
module SVG = struct ... end
let _ = Hashtbl.add devices "SVG" (module SVG : DEVICE)
```

```python
module PDF = struct ... end
let _ = Hashtbl.add devices "PDF" (module PDF : DEVICE)
```

We can then select one implementation based on command-line arguments, for instance:

```python
let parse_cmdline () = ...
module Device =
    (val (let device_name = parse_cmdline () in
        try Hashtbl.find devices device_name
        with Not_found ->
          untf.eprintf "Unknown device %s\n" device_name;
        exit 2)
    : DEVICE)
```

Alternatively, the selection can be performed within a function:

```python
let draw_using_device device_name picture =
    let module Device =
        (val (Hashtbl.find devices device_name) : DEVICE)
    in
    Device.draw picture
```

**Advanced examples** With first-class modules, it is possible to parametrize some code over the implementation of a module without using a functor.

```python
let sort (type s) (module Set : Set.S with type elt = s) l =
    Set (List.fold_right Set.add l Set.empty)
val sort : (module Set.S with type elt = 's) -> 's list -> 's list = <fun>
```

To use this function, one can wrap the `Set.Make` functor:

```python
let make_set (type s) cmp =
    let module S = Set.Make(struct
        type t = s
        let compare = cmp
    end) in
    (module S : Set.S with type elt = s)
val make_set : ('s -> 's -> int) -> (module Set.S with type elt = 's) = <fun>
```
Local substitutions behave like destructive substitutions (`with... := ...`) but instead of being applied to a whole signature after the fact, they are introduced during the specification of the signature, and will apply to all the items that follow.

This provides a convenient way to introduce local names for types and modules when defining a signature:

```haskell
module type S = sig
    type t
    module Sub : sig
        type outer := t
        type t
        val to_outer : t -> outer
end
end

module type S =
    sig type t module Sub : sig type t val to_outer : t -> t/2 end
end
```

Note that, unlike type declarations, type substitution declarations are not recursive, so substitutions like the following are rejected:

```haskell
# module type S = sig
    type 'a poly_list := [ `Cons of 'a * 'a poly_list | `Nil ]
end ;

Error: Unbound type constructor poly_list
```

### 12.7.3 Module type substitutions

(Introduced in OCaml 4.13)

```
mod-constraint ::= ...
                  | module type modtype-path = module-type
                  | module type modtype-path := module-type
```

Module type substitution essentially behaves like type substitutions. They are useful to refine an abstract module type in a signature into a concrete module type,

```haskell
# module type ENDO = sig
    module type T
    module F: T -> T
end

module Endo(X: sig module type T end): ENDO with module type T = X.T =
    struct
        module type T = X.T
        module F(X:T) = X
    end;

module type ENDO = sig module type T module F : T -> T end
module Endo :
    functor (X : sig module type T end) ->
    sig module type T = X.T module F : T -> T end
```
## 12.6 Recovering the type of a module

(Introduced in OCaml 3.12)

```
module-type ::= ...
               | module type of module-expr
```

The construction `module type of module-expr` expands to the module type (signature or functor type) inferred for the module expression `module-expr`. To make this module type reusable in many situations, it is intentionally not strengthened: abstract types and datatypes are not explicitly related with the types of the original module. For the same reason, module aliases in the inferred type are expanded.

A typical use, in conjunction with the signature-level `include` construct, is to extend the signature of an existing structure. In that case, one wants to keep the types equal to types in the original module. This can be done using the following idiom.

```sml
module type MYHASH = sig
    include module type of struct include Hashtbl end
    val replace: ('a, 'b) t -> 'a -> 'b -> unit
end
```

The signature `MYHASH` then contains all the fields of the signature of the module `Hashtbl` (with strengthened type definitions), plus the new field `replace`. An implementation of this signature can be obtained easily by using the `include` construct again, but this time at the structure level:

```sml
module MyHash : MYHASH = struct
    include Hashtbl
    let replace t k v = remove t k; add t k v
end
```

Another application where the absence of strengthening comes handy, is to provide an alternative implementation for an existing module.

```sml
module MySet : module type of Set = struct
    ...
end
```

This idiom guarantees that `MySet` is compatible with `Set`, but allows it to represent sets internally in a different way.

## 12.7 Substituting inside a signature

### 12.7.1 Destructive substitutions

(Introduced in OCaml 3.12, generalized in 4.06)

```
mod-constraint ::= ...
               | type [type-params] typeconstr-name := typexpr
               | module module-path := extended-module-path
```

A “destructive” substitution (`with... := ...`) behaves essentially like normal signature constraints (`with... = ...`), but it additionally removes the redefined type or module from the signature.
It is also possible to substitute a concrete module type with an equivalent module types.

module type A = sig

type x

module type R = sig

type a = A of x

type b

end

end

module type S = sig

type a = A of int

type b

end

module type B = A with type x = int and module type R = S

However, such substitutions are never necessary.

Destructive module type substitution removes the module type substitution from the signature

# module type ENDO' = ENDO with module type T := ENDO;;

module type ENDO' = sig module F : ENDO -> ENDO end

If the right hand side of the substitution is not a path, then the destructive substitution is only valid if the left-hand side of the substitution is never used as the type of a first-class module in the original module type.

module type T = sig module type S val x: (module S) end

module type Error = T with module type S := sig end

Error: This `with` constraint S := sig end makes a packed module ill-formed.

## 12.8 Type-level module aliases

(Introduced in OCaml 4.02)

specification ::= ...
| module module-name = module-path

The above specification, inside a signature, only matches a module definition equal to *module-path*. Conversely, a type-level module alias can be matched by itself, or by any supertype of the type of the module it references.

There are several restrictions on *module-path*:

1. it should be of the form $M_0.M_1...M_n$ (i.e. without functor applications);

2. inside the body of a functor, $M_0$ should not be one of the functor parameters;

3. inside a recursive module definition, $M_0$ should not be one of the recursively defined modules.

Such specifications are also inferred. Namely, when *P* is a path satisfying the above constraints,

module N = P
Prior to OCaml 4.06, there were a number of restrictions: one could only remove types and modules at the outermost level (not inside submodules), and in the case of `with type` the definition had to be another type constructor with the same type parameters.

A natural application of destructive substitution is merging two signatures sharing a type name.

```ocaml
module type Printable = sig
    type t
    val print : Format formatter -> t -> unit
end

module type Comparable = sig
    type t
    val compare : t -> t -> int
end

module type PrintableComparable = sig
    include Printable
    include Comparable with type t := t
end
```

One can also use this to completely remove a field:

```ocaml
module type S = Comparable with type t := int
module type S = sig val compare : int -> int -> int end
```

or to rename one:

```ocaml
module type S = sig
    type u
    include Comparable with type t := u
end

module type S = sig type u val compare : u -> u -> int end
```

Note that you can also remove manifest types, by substituting with the same type.

```ocaml
module type ComparableInt = Comparable with type t = int ;;
module type ComparableInt = sig type t = int val compare : t -> t -> int end
```

```ocaml
module type CompareInt = ComparableInt with type t := int
module type CompareInt = sig val compare : int -> int -> int end
```

## 12.7.2 Local substitution declarations

(Introduced in OCaml 4.08, module type substitution introduced in 4.13)

```
specification ::= ...
| type type-subst {and type-subst}
| module module-name := extended-module-path
| module type module-name := module-type

type-subst ::= [type-params] typeconstr-name := typexpr {type-constraint}
```
has type

module N = P

Type-level module aliases are used when checking module path equalities. That is, in a context where module name *N* is known to be an alias for *P*, not only these two module paths check as equal, but *F* (*N*) and *F* (*P*) are also recognized as equal. In the default compilation mode, this is the only difference with the previous approach of module aliases having just the same module type as the module they reference.

When the compiler flag `-no-alias-deps` is enabled, type-level module aliases are also exploited to avoid introducing dependencies between compilation units. Namely, a module alias referring to a module inside another compilation unit does not introduce a link-time dependency on that compilation unit, as long as it is not dereferenced; it still introduces a compile-time dependency if the interface needs to be read, i.e. if the module is a submodule of the compilation unit, or if some type components are referred to. Additionally, accessing a module alias introduces a link-time dependency on the compilation unit containing the module referenced by the alias, rather than the compilation unit containing the alias. Note that these differences in link-time behavior may be incompatible with the previous behavior, as some compilation units might not be extracted from libraries, and their side-effects ignored.

These weakened dependencies make possible to use module aliases in place of the `-pack` mechanism. Suppose that you have a library `Mylib` composed of modules `A` and `B`. Using `-pack`, one would issue the command line

ocamlc -pack a.cmo b.cmo -o mylib.cmo

and as a result obtain a `Mylib` compilation unit, containing physically `A` and `B` as submodules, and with no dependencies on their respective compilation units. Here is a concrete example of a possible alternative approach:

1. Rename the files containing `A` and `B` to `Mylib__A` and `Mylib__B`.

2. Create a packing interface `Mylib.ml`, containing the following lines.

module A = Mylib__A

module B = Mylib__B

3. Compile `Mylib.ml` using `-no-alias-deps`, and the other files using `-no-alias-deps` and `-open Mylib` (the last one is equivalent to adding the line `open! Mylib` at the top of each file).

ocamlc -c -no-alias-deps Mylib.ml

ocamlc -c -no-alias-deps -open Mylib Mylib__*.mli Mylib__*.ml

4. Finally, create a library containing all the compilation units, and export all the compiled interfaces.

ocamlc -a Mylib*.cmo -o Mylib.cma
Local substitutions behave like destructive substitutions (`with... :=...`) but instead of being applied to a whole signature after the fact, they are introduced during the specification of the signature, and will apply to all the items that follow.

This provides a convenient way to introduce local names for types and modules when defining a signature:

```hkl
module type S = sig
type t
module Sub : sig
type outer := t
type t
val to_outer : t -> outer
end
end
module type S =
sig type t module Sub : sig type t val to_outer : t -> t/2 end
end
```

Note that, unlike type declarations, type substitution declarations are not recursive, so substitutions like the following are rejected:

```hkl
# module type S = sig
type 'a poly_list := [ `Cons of 'a * 'a poly_list | `Nil ]
end ;
```

```
Error: Unbound type constructor poly_list
```

Local substitutions can also be used to give a local name to a type or a module type introduced by a functor application:

```hkl
# module type F = sig
type set := Set.Make(Int).t

module type Type = sig type t end
module Nest : Type -> sig module type T = Type end

module type T := Nest(Int).T

val set: set
val m : (module T)
end;

module type F =
sig
  module type Type = sig type t end
  module Nest : Type -> sig module type T = Type end
  val set : Set.Make(Int).t
  val m : (module Nest(Int).T)
end
```

Local module type substitutions are subject to the same limitations as module type substitutions, see section 12.7.3.
This approach lets you access `A` and `B` directly inside the library, and as `Mylib.A` and `Mylib.B` from outside. It also has the advantage that `Mylib` is no longer monolithic: if you use `Mylib.A`, only `Mylib._A` will be linked in, not `Mylib._B`.

Note the use of double underscores in `Mylib._A` and `Mylib._B`. These were chosen on purpose; the compiler uses the following heuristic when printing paths: given a path `Lib_fooBar`, if `Lib.FooBar` exists and is an alias for `Lib_fooBar`, then the compiler will always display `Lib.FooBar` instead of `Lib_fooBar`. This way the long `Mylib._` names stay hidden and all the user sees is the nicer dot names. This is how the OCaml standard library is compiled.

## 12.9 Overriding in open statements

(Introduced in OCaml 4.01)

```
definition ::= ...
               | open! module-path

specification ::= ...
                  | open! module-path

expr         ::= ...
               | let open! module-path in expr

class-body-type ::= ...
                    | let open! module-path in class-body-type

class-expr   ::= ...
               | let open! module-path in class-expr
```

Since OCaml 4.01, `open` statements shadowing an existing identifier (which is later used) trigger the warning 44. Adding a `!` character after the `open` keyword indicates that such a shadowing is intentional and should not trigger the warning.

This is also available (since OCaml 4.06) for local opens in class expressions and class type expressions.

## 12.10 Generalized algebraic datatypes

Generalized algebraic datatypes, or GADTs, extend usual sum types in two ways: constraints on type parameters may change depending on the value constructor, and some type variables may be existentially quantified. They are described in chapter 7.

(Introduced in OCaml 4.00)

```
constr-decl ::= ...
               | constr-name : [constr-args ->] typexpr

type-param ::= ...
               | [variance] _
```

Refutation cases. (Introduced in OCaml 4.03)
### 12.7.3 Module type substitutions

(Introduced in OCaml 4.13)

$$ \mathit{mod-constraint} ::= \dots \\ | \mathit{module type} \ \mathit{modtype-path} = \mathit{module-type} \\ | \mathit{module type} \ \mathit{modtype-path} := \mathit{module-type} $$

Module type substitution essentially behaves like type substitutions. They are useful to refine an abstract module type in a signature into a concrete module type,

```hml
# module type ENDO = sig
module type T
module F: T -> T
end
module Endo(X: sig module type T end): ENDO with module type T = X.T =
struct
  module type T = X.T
  module F(X:T) = X
end;;
module type ENDO = sig module type T module F : T -> T end
module Endo :
(X : sig module type T end) ->
  sig module type T = X.T module F : T -> T end
```

It is also possible to substitute a concrete module type with an equivalent module types.

```hml
module type A = sig
type x
module type R = sig
type a = A of x
type b
end
end
module type S = sig
type a = A of int
type b
end
module type B = A with type x = int and module type R = S
However, such substitutions are never necessary.
```

Destructive module type substitution removes the module type substitution from the signature

```hml
# module type ENDO' = ENDO with module type T := ENDO;;
module type ENDO' = sig module F : ENDO -> ENDO end
```

### Limitations

If the right hand side of a module type substitution or a local module type substitution is not a *modtype-path*, then the destructive substitution is only valid if the left-hand side of the substitution is never used as the type of a first-class module in the original module type.
$$ matching-case ::= pattern [when expr] -> expr \\ | pattern -> . $$

Explicit naming of existentials. (Introduced in OCaml 4.13.0)

$$ pattern ::= ... \\ | constr ( type {typeconstr-name}^+ ) ( pattern ) $$

## 12.11 Syntax for Bigarray access

(Introduced in Objective Caml 3.00)

$$ expr ::= ... \\ | expr . { expr {, expr} } \\ | expr . { expr {, expr} } <- expr $$

This extension provides syntactic sugar for getting and setting elements in the arrays provided by the `Bigarray` [28.5] module.

The short expressions are translated into calls to functions of the `Bigarray` module as described in the following table.

<table><thead><tr><th>expression</th><th>translation</th></tr></thead><tbody><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>}</td><td>Bigarray Array1.get expr<sub>0</sub> expr<sub>1</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>} <- expr</td><td>Bigarray Array1.set expr<sub>0</sub> expr<sub>1</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>}</td><td>Bigarray Array2.get expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>} <- expr</td><td>Bigarray Array2.set expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>, expr<sub>3</sub>}</td><td>Bigarray Array3.get expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr<sub>3</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>, expr<sub>3</sub>} <- expr</td><td>Bigarray Array3.set expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr<sub>3</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, ..., expr<sub>n</sub>}</td><td>Bigarray Genarray.get expr<sub>0</sub> [| expr<sub>1</sub>, ..., expr<sub>n</sub> |]</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, ..., expr<sub>n</sub>} <- expr</td><td>Bigarray Genarray.set expr<sub>0</sub> [| expr<sub>1</sub>, ..., expr<sub>n</sub> |] expr</td></tr></tbody></table>

The last two entries are valid for any $n > 3$.

## 12.12 Attributes

(Introduced in OCaml 4.02, infix notations for constructs other than expressions added in 4.03)

Attributes are “decorations” of the syntax tree which are mostly ignored by the type-checker but can be used by external tools. An attribute is made of an identifier and a payload, which can be a structure, a type expression (prefixed with `:`), a signature (prefixed with `:`) or a pattern (prefixed with `?`) optionally followed by a `when` clause:
module type T = sig module type S val x: (module S) end

module type Error = T with module type S := sig end

Error: This with constraint S := sig end makes a packed module ill-formed.
(see manual section 12.7.3)

module type T = sig module type S := sig end val x: (module S) end

Error: The module type S is not a valid type for a packed module:
it is defined as a local substitution (temporary name)
for an anonymous module type. (see manual section 12.7.3)

## 12.8 Type-level module aliases

(Introduced in OCaml 4.02)

specification ::= ...
| module module-name = module-path

The above specification, inside a signature, only matches a module definition equal to module-path. Conversely, a type-level module alias can be matched by itself, or by any supertype of the type of the module it references.

There are several restrictions on module-path:

1. it should be of the form $M_0.M_1...M_n$ (i.e. without functor applications);

2. inside the body of a functor, $M_0$ should not be one of the functor parameters;

3. inside a recursive module definition, $M_0$ should not be one of the recursively defined modules.

Such specifications are also inferred. Namely, when $P$ is a path satisfying the above constraints,

module N = P
has type

module N = P

Type-level module aliases are used when checking module path equalities. That is, in a context where module name $N$ is known to be an alias for $P$, not only these two module paths check as equal, but $F(N)$ and $F(P)$ are also recognized as equal. In the default compilation mode, this is the only difference with the previous approach of module aliases having just the same module type as the module they reference.

When the compiler flag `-no-alias-deps` is enabled, type-level module aliases are also exploited to avoid introducing dependencies between compilation units. Namely, a module alias referring to a module inside another compilation unit does not introduce a link-time dependency on that compilation unit, as long as it is not dereferenced; it still introduces a compile-time dependency if the interface needs to be read, i.e. if the module is a submodule of the compilation unit, or if some type components are referred to. Additionally, accessing a module alias introduces a link-time dependency on the compilation unit containing the module referenced by the alias, rather than the compilation unit containing the alias. Note that these differences in link-time behavior may be
```
attr-id ::= lowercase-ident
           | capitalized-ident
           | attr-id . attr-id

attr-payload ::= [module-items]
                  | : typexpr
                  | : [specification]
                  | ? pattern [when expr]
```

The first form of attributes is attached with a postfix notation on "algebraic" categories:

```
attribute ::= [@ attr-id attr-payload ]
expr ::= ...
       | expr attribute
typexpr ::= ...
           | typexpr attribute
pattern ::= ...
           | pattern attribute
module-expr ::= ...
               | module-expr attribute
module-type ::= ...
               | module-type attribute
class-expr ::= ...
               | class-expr attribute
class-type ::= ...
               | class-type attribute
```

This form of attributes can also be inserted after the `tag-name` in polymorphic variant type expressions (`tag-spec-first`, `tag-spec`, `tag-spec-full`) or after the `method-name` in `method-type`.

The same syntactic form is also used to attach attributes to labels and constructors in type declarations:

```
field-decl ::= [mutable] field-name : poly-typexpr {attribute}
constr-decl ::= (constr-name | () ) [of constr-args] {attribute}
```

Note: when a label declaration is followed by a semi-colon, attributes can also be put after the semi-colon (in which case they are merged to those specified before).

The second form of attributes are attached to "blocks" such as type declarations, class fields, etc:
incompatible with the previous behavior, as some compilation units might not be extracted from libraries, and their side-effects ignored.

These weakened dependencies make possible to use module aliases in place of the `-pack` mechanism. Suppose that you have a library `Mylib` composed of modules `A` and `B`. Using `-pack`, one would issue the command line

```
ocamlc -pack a.cmo b.cmo -o mylib.cmo
```

and as a result obtain a `Mylib` compilation unit, containing physically `A` and `B` as submodules, and with no dependencies on their respective compilation units. Here is a concrete example of a possible alternative approach:

1. Rename the files containing `A` and `B` to `Mylib__A` and `Mylib__B`.

2. Create a packing interface `Mylib.ml`, containing the following lines.

```lyre
module A = Mylib__A
```

```lyre
module B = Mylib__B
```

3. Compile `Mylib.ml` using `-no-alias-deps`, and the other files using `-no-alias-deps` and `-open Mylib` (the last one is equivalent to adding the line `open! Mylib` at the top of each file).

```sh
ocamlc -c -no-alias-deps Mylib.ml
```

```sh
ocamlc -c -no-alias-deps -open Mylib Mylib_*.mli Mylib_*.ml
```

4. Finally, create a library containing all the compilation units, and export all the compiled interfaces.

```sh
ocamlc -a Mylib*.cmo -o Mylib.cma
```

This approach lets you access `A` and `B` directly inside the library, and as `Mylib.A` and `Mylib.B` from outside. It also has the advantage that `Mylib` is no longer monolithic: if you use `Mylib.A`, only `Mylib__A` will be linked in, not `Mylib__B`.

Note the use of double underscores in `Mylib__A` and `Mylib__B`. These were chosen on purpose; the compiler uses the following heuristic when printing paths: given a path `Lib__fooBar`, if `Lib.FooBar` exists and is an alias for `Lib__fooBar`, then the compiler will always display `Lib.FooBar` instead of `Lib__fooBar`. This way the long `Mylib__` names stay hidden and all the user sees is the nicer dot names. This is how the OCaml standard library is compiled.

## 12.9 Overriding in open statements

(Introduced in OCaml 4.01)
item-attribute ::= [@@ attr-id attr-payload ]

typedef ::= ...

| typedef item-attribute

exception-definition ::= exception constr-decl

| exception constr-name = constr

module-items ::= [;;] (definition | expr {item-attribute}) {[;;] definition | ;; expr {item-attribute}} [;

class-binding ::= ...

| class-binding item-attribute

class-spec ::= ...

| class-spec item-attribute

classtype-def ::= ...

| classtype-def item-attribute

definition ::= let [rec] let-binding {and let-binding}

| external value-name : typexpr = external-declaration {item-attribute}

| type-definition

| exception-definition {item-attribute}

| class-definition

| classtype-definition

| module module-name { ( module-name : module-type ) } [ : module-type ]
| = module-expr {item-attribute}

| module type modtype-name = module-type {item-attribute}

| open module-path {item-attribute}

| include module-expr {item-attribute}

| module rec module-name : module-type =
| module-expr {item-attribute}

{and module-name : module-type = module-expr
{item-attribute}}

specification ::= val value-name : typexpr {item-attribute}

| external value-name : typexpr = external-declaration {item-attribute}

| type-definition

| exception constr-decl {item-attribute}

| class-specification

| classtype-definition

| module module-name : module-type {item-attribute}

| module module-name { ( module-name : module-type ) } : module-type {item-attribute}

| module type modtype-name {item-attribute}

| module type modtype-name = module-type {item-attribute}

| open module-path {item-attribute}

| include module-type {item-attribute}

class-field-spec ::= ...

| class-field-spec item-attribute

class-field ::= ...

| class-field item-attribute
definition ::= ...
| open! module-path

specification ::= ...
| open! module-path

expr ::= ...
| let open! module-path in expr

class-body-type ::= ...
| let open! module-path in class-body-type

class-expr ::= ...
| let open! module-path in class-expr

Since OCaml 4.01, `open` statements shadowing an existing identifier (which is later used) trigger the warning 44. Adding a `!` character after the `open` keyword indicates that such a shadowing is intentional and should not trigger the warning.

This is also available (since OCaml 4.06) for local opens in class expressions and class type expressions.

## 12.10 Generalized algebraic datatypes

Generalized algebraic datatypes, or GADTs, extend usual sum types in two ways: constraints on type parameters may change depending on the value constructor, and some type variables may be existentially quantified. They are described in chapter 7.

(Introduced in OCaml 4.00)

constr-decl ::= ...
| constr-name : [constr-args ->] typexpr
type-param ::= ...
| [variance] _

Refutation cases. (Introduced in OCaml 4.03)

matching-case ::= pattern [when expr] -> expr
| pattern -> .

Explicit naming of existentials. (Introduced in OCaml 4.13.0)

pattern ::= ...
| constr ( type {typeconstr-name} + ) ( pattern )
A third form of attributes appears as stand-alone structure or signature items in the module or class sub-languages. They are not attached to any specific node in the syntax tree:

<table><tr><td><code>floating-attribute</code></td><td>::=</td><td><code>[@@@ attr-id attr-payload ]</code></td></tr><tr><td><code>definition</code></td><td>::=</td><td><code>...</code></td></tr><tr><td></td><td></td><td><code>| floating-attribute</code></td></tr><tr><td><code>specification</code></td><td>::=</td><td><code>...</code></td></tr><tr><td></td><td></td><td><code>| floating-attribute</code></td></tr><tr><td><code>class-field-spec</code></td><td>::=</td><td><code>...</code></td></tr><tr><td></td><td></td><td><code>| floating-attribute</code></td></tr><tr><td><code>class-field</code></td><td>::=</td><td><code>...</code></td></tr><tr><td></td><td></td><td><code>| floating-attribute</code></td></tr></table>

(Note: contrary to what the grammar above describes, *item-attributes* cannot be attached to these floating attributes in *class-field-spec* and *class-field*.)

It is also possible to specify attributes using an infix syntax. For instance:

<table><tr><td><code>let[@foo] x = 2 in x + 1</code></td><td>::=</td><td><code>(let x = 2 [@foo] in x + 1)</code></td></tr><tr><td><code>begin[@foo][@bar x] ... end</code></td><td>::=</td><td><code>(begin ... end)[@foo][@bar x]</code></td></tr><tr><td><code>module[@foo] M = ...</code></td><td>::=</td><td><code>module M = ... [@foo]</code></td></tr><tr><td><code>type[@foo] t = T</code></td><td>::=</td><td><code>type t = T [@foo]</code></td></tr><tr><td><code>method[@foo] m = ...</code></td><td>::=</td><td><code>method m = ... [@foo]</code></td></tr></table>

For `let`, the attributes are applied to each bindings:

<table><tr><td><code>let[@foo] x = 2 and y = 3 in x + y</code></td><td>::=</td><td><code>(let x = 2 [@foo] and y = 3 in x + y)</code></td></tr><tr><td><code>let[@foo] x = 2</code></td><td></td><td></td></tr><tr><td><code>and[@bar] y = 3 in x + y</code></td><td>::=</td><td><code>(let x = 2 [@foo] and y = 3 [@bar] in x + y)</code></td></tr></table>

### 12.12.1 Built-in attributes

Some attributes are understood by the type-checker:

* "ocaml.warning" or "warning", with a string literal payload. This can be used as floating attributes in a signature/structure/object/object type. The string is parsed and has the same effect as the `-w` command-line option, in the scope between the attribute and the end of the current signature/structure/object/object type. The attribute can also be attached to any kind of syntactic item which support attributes (such as an expression, or a type expression) in which case its scope is limited to that item. Note that it is not well-defined which scope is used for a specific warning. This is implementation dependent and can change between versions. Some warnings are even completely outside the control of "ocaml.warning" (for instance, warnings 1, 2, 14, 29 and 50).

* "ocaml.warning" or "warnerror", with a string literal payload. Same as "ocaml.warning", for the `-warn-error` command-line option.
## 12.11 Syntax for Bigarray access

(Introduced in Objective Caml 3.00)

$$ 
\begin{array}{l}
expr ::= ... \\
\qquad | expr . \{ expr {, expr} \} \\
\qquad | expr . \{ expr {, expr} \} <- expr
\end{array}
$$

This extension provides syntactic sugar for getting and setting elements in the arrays provided by the `Bigarray` [29.5] module.

The short expressions are translated into calls to functions of the `Bigarray` module as described in the following table.

<table><thead><tr><th>expression</th><th>translation</th></tr></thead><tbody><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>}</td><td>Bigarray Array1.get expr<sub>0</sub> expr<sub>1</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>} <- expr</td><td>Bigarray Array1.set expr<sub>0</sub> expr<sub>1</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>}</td><td>Bigarray Array2.get expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>} <- expr</td><td>Bigarray Array2.set expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>, expr<sub>3</sub>}</td><td>Bigarray Array3.get expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr<sub>3</sub></td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, expr<sub>2</sub>, expr<sub>3</sub>} <- expr</td><td>Bigarray Array3.set expr<sub>0</sub> expr<sub>1</sub> expr<sub>2</sub> expr<sub>3</sub> expr</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, ..., expr<sub>n</sub>}</td><td>Bigarray Genarray.get expr<sub>0</sub> [| expr<sub>1</sub>, ..., expr<sub>n</sub> |]</td></tr><tr><td>expr<sub>0</sub>.{expr<sub>1</sub>, ..., expr<sub>n</sub>} <- expr</td><td>Bigarray Genarray.set expr<sub>0</sub> [| expr<sub>1</sub>, ..., expr<sub>n</sub> |] expr</td></tr></tbody></table>

The last two entries are valid for any $n > 3$.

## 12.12 Attributes

(Introduced in OCaml 4.02, infix notations for constructs other than expressions added in 4.03)

Attributes are “decorations” of the syntax tree which are mostly ignored by the type-checker but can be used by external tools. An attribute is made of an identifier and a payload, which can be a structure, a type expression (prefixed with `:`), a signature (prefixed with `:`) or a pattern (prefixed with `?`) optionally followed by a `when` clause:

$$ 
\begin{array}{l}
attr-id ::= lowercase-ident \\
           | capitalized-ident \\
           | attr-id . attr-id
\end{array}
$$

$$ 
\begin{array}{l}
attr-payload ::= [module-items] \\
                 | : typexpr \\
                 | : [specification] \\
                 | ? pattern [when expr]
\end{array}
$$

The first form of attributes is attached with a postfix notation on “algebraic” categories:
* "ocaml.alert" or "alert": see section 12.21.

* "ocaml.dePRECATED" or "deprecated": alias for the "deprecated" alert, see section 12.21.

* "ocaml.dePRECATEDmutable"" or "deprecated mutable". Can be applied to a mutable record
  label. If the label is later used to modify the field (with "expr.l <- expr"), the "deprecated"
  alert will be triggered. If the payload of the attribute is a string literal, the alert message
  includes this text.

* "ocaml.ppwarning" or "ppwarning", in any context, with a string literal payload. The text
is reported as warning (22) by the compiler (currently, the warning location is the location
of the string payload). This is mostly useful for preprocessors which need to communicate
warnings to the user. This could also be used to mark explicitly some code location for further
inspection.

* "ocaml.warn_on_literal_pattern" or "warn_on_literal_pattern" annotate constructors in
  type definition. A warning (52) is then emitted when this constructor is pattern matched with
  a constant literal as argument. This attribute denotes constructors whose argument is purely
  informative and may change in the future. Therefore, pattern matching on this argument with
  a constant literal is unreliable. For instance, all built-in exception constructors are marked as
  "warn_on_literal_pattern". Note that, due to an implementation limitation, this warning (52)
  is only triggered for single argument constructor.

* "ocaml.tailcall" or "tailcall" can be applied to function application in order to check that the
call is tailcall optimized. If it is not the case, a warning (51) is emitted.

* "ocaml inline" or "inline" take either "never", "always" or nothing as payload on a function
or functor definition. If no payload is provided, the default value is "always". This payload
controls when applications of the annotated functions should be inlined.

* "ocaml.inlined" or "inlined" can be applied to any function or functor application to check
that the call is inlined by the compiler. If the call is not inlined, a warning (55) is emitted.

* "ocaml.noalloc", "ocaml.unboxed" and "ocaml.untagged" or "noalloc", "unboxed" and "un-
tagged" can be used on external definitions to obtain finer control over the C-to-OCaml
interface. See 22.11 for more details.

* "ocaml.immediate" or "immediate" applied on an abstract type mark the type as having
a non-pointer implementation (e.g. "int", "bool", "char" or enumerated types). Mutation
of these immediate types does not activate the garbage collector's write barrier, which can
significantly boost performance in programs relying heavily on mutable state.

* "ocaml.immediate64" or "immediate64" applied on an abstract type mark the type as hav-
ing a non-pointer implementation on 64 bit platforms. No assumption is made on other
platforms. In order to produce a type with the "immediate64" attribute, one must use
"Sys.Immediate64.Make" functor.

* `ocaml.unboxed` or `unboxed` can be used on a type definition if the type is a single-field record or a concrete type with a single constructor that has a single argument. It tells the compiler
<table><tr><td>attribute</td><td>::=</td><td>[@ attr-id attr-payload ]</td></tr><tr><td>expr</td><td>::=</td><td>...<br>| expr attribute</td></tr><tr><td>typexpr</td><td>::=</td><td>...<br>| typexpr attribute</td></tr><tr><td>pattern</td><td>::=</td><td>...<br>| pattern attribute</td></tr><tr><td>module-expr</td><td>::=</td><td>...<br>| module-expr attribute</td></tr><tr><td>module-type</td><td>::=</td><td>...<br>| module-type attribute</td></tr><tr><td>class-expr</td><td>::=</td><td>...<br>| class-expr attribute</td></tr><tr><td>class-type</td><td>::=</td><td>...<br>| class-type attribute</td></tr></table>

This form of attributes can also be inserted after the `tag-name` in polymorphic variant type expressions (`tag-spec-first`, `tag-spec`, `tag-spec-full`) or after the `method-name` in `method-type`.

The same syntactic form is also used to attach attributes to labels and constructors in type declarations:

$$
\begin{align*}
\mathit{field-decl} &::= [\mathit{mutable}] \mathit{field-name} : \mathit{poly-typexpr} \{\mathit{attribute}\} \\
\mathit{constr-decl} &::= (\mathit{constr-name} | (\)) [\mathit{of} \ \mathit{constr-args}] \{\mathit{attribute}\}
\end{align*}
$$

Note: when a label declaration is followed by a semi-colon, attributes can also be put after the semi-colon (in which case they are merged to those specified before).

The second form of attributes are attached to “blocks” such as type declarations, class fields, etc:
to optimize the representation of the type by removing the block that represents the record or
the constructor (i.e. a value of this type is physically equal to its argument). In the case of
GADTs, an additional restriction applies: the argument must not be an existential variable,
represented by an existential type variable, or an abstract type constructor applied to an
existential type variable.

* `ocaml.boxed` or `boxed` can be used on type definitions to mean the opposite of `ocaml.unboxed`: keep the unoptimized representation of the type. When there is no annotation, the default is currently `boxed` but it may change in the future.

* `ocaml.local` or `local` take either `never`, `always`, `maybe` or nothing as payload on a function definition. If no payload is provided, the default is `always`. The attribute controls an optimization which consists in compiling a function into a static continuation. Contrary to inlining, this optimization does not duplicate the function's body. This is possible when all references to the function are full applications, all sharing the same continuation (for instance, the returned value of several branches of a pattern matching). `never` disables the optimization, `always` asserts that the optimization applies (otherwise a warning 55 is emitted) and `maybe` lets the optimization apply when possible (this is the default behavior when the attribute is not specified). The optimization is implicitly disabled when using the bytecode compiler in debug mode (-g), and for functions marked with an `ocaml inline always` or `ocaml.unrolled` attribute which supersede `ocaml.local`.

```ocaml
module X = struct
    [@@@warning "+9"] (* locally enable warning 9 in this structure *)
    ...
end
[@@deprecated "Please use module 'Y' instead."]
```

```ocaml
let x = begin[@warning "+9"] [...] end
```

```ocaml
type t = A | B
[@@deprecated "Please use type 's' instead."]
```

```ocaml
let fires_warning_22 x =
    assert (x >= 0) [@ppwarning "TODO: remove this later"]

Warning 22 [preprocessor]: TODO: remove this later
```

```ocaml
let rec is_a_tail_call = function
| [] -> ()
| _ :: q -> (is_a_tail_call[@tailcall]) q
```

```ocaml
let rec not_a_tail_call = function
| [] -> []
| x :: q -> x :: (not_a_tail_call[@tailcall]) q
```

Warning 51 [wrong-tailcall-expectation]: expected tailcall
item-attribute ::= [@@ attr-id attr-payload ]

typedef ::= ...

| typedef item-attribute

exception-definition ::= exception constr-decl

| exception constr-name = constr

module-items ::= [;;] (definition | expr {item-attribute}) {[;;] definition | ;; expr {item-attribute}} [;

class-binding ::= ...

| class-binding item-attribute

class-spec ::= ...

| class-spec item-attribute

classtype-def ::= ...

| classtype-def item-attribute

definition ::= let [rec] let-binding {and let-binding}

| external value-name : typexpr = external-declaration {item-attribute}

| type-definition

| exception-definition {item-attribute}

| class-definition

| classtype-definition

| module module-name { ( module-name : module-type ) } [ : module-type ]
| = module-expr {item-attribute}

| module type modtype-name = module-type {item-attribute}

| open module-path {item-attribute}

| include module-expr {item-attribute}

| module rec module-name : module-type =
| module-expr {item-attribute}

{and module-name : module-type = module-expr
{item-attribute}}

specification ::= val value-name : typexpr {item-attribute}

| external value-name : typexpr = external-declaration {item-attribute}

| type-definition

| exception constr-decl {item-attribute}

| class-specification

| classtype-definition

| module module-name : module-type {item-attribute}

| module module-name { ( module-name : module-type ) } : module-type {item-attribute}

| module type modtype-name {item-attribute}

| module type modtype-name = module-type {item-attribute}

| open module-path {item-attribute}

| include module-type {item-attribute}

class-field-spec ::= ...

| class-field-spec item-attribute

class-field ::= ...

| class-field item-attribute
let f x = x [@@inline]

let () = (f[@inlined]) ()

type fragile =
  | Int of int [@warn_on_literal_pattern]
  | String of string [@warn_on_literal_pattern]

let fragile_match_1 = function
| Int 0 -> ()
| _  -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (see manual section 13.5.3)

val fragile_match_1 : fragile -> unit = <fun>

let fragile_match_2 = function
| String "constant" -> ()
| _ -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (see manual section 13.5.3)

val fragile_match_2 : fragile -> unit = <fun>

module Immediate: sig
type t [@@immediate]
val x: t ref

end = struct
  type t = A | B
  let x = ref A

end

module Int_or_int64 : sig
type t [@@immediate64]
val zero : t
val one : t
val add : t -> t -> t
end = struct

include Sys.Immediate64.Make(Int)(Int64)

module type S = sig
  val zero : t
  val one : t
  val add : t -> t -> t
A third form of attributes appears as stand-alone structure or signature items in the module or class sub-languages. They are not attached to any specific node in the syntax tree:

`floating-attribute ::= [@@ attr-id attr-payload ]`

`definition ::= ...`
| `floating-attribute`

`specification ::= ...`
| `floating-attribute`

`class-field-spec ::= ...`
| `floating-attribute`

`class-field ::= ...`
| `floating-attribute`

(Note: contrary to what the grammar above describes, *item-attributes* cannot be attached to these floating attributes in *class-field-spec* and *class-field*.)

It is also possible to specify attributes using an infix syntax. For instance:

```
let[@foo] x = 2 in x + 1          === (let x = 2 [@@foo] in x + 1)
begin[@foo][@bar x] ... end       === (begin ... end)[@foo][@bar x]
module[@foo] M = ...             === module M = ... [@foo]
type[@foo] t = T                 === type t = T [@foo]
method[@foo] m = ...             === method m = ... [@foo]
```

For `let`, the attributes are applied to each bindings:

```
let[@foo] x = 2 and y = 3 in x + y === (let x = 2 [@@foo] and y = 3 in x + y)
let[@foo] x = 2
and[@bar] y = 3 in x + y           === (let x = 2 [@@foo] and y = 3 [@bar] in x + y)
```

### 12.12.1 Built-in attributes

Some attributes are understood by the compiler:

* "ocaml.warning" or "warning", with a string literal payload. This can be used as floating attributes in a signature/structure/object/object type. The string is parsed and has the same effect as the `-w` command-line option, in the scope between the attribute and the end of the current signature/structure/object/object type. The attribute can also be attached to any kind of syntactic item which support attributes (such as an expression, or a type expression) in which case its scope is limited to that item. Note that it is not well-defined which scope is used for a specific warning. This is implementation dependent and can change between versions. Some warnings are even completely outside the control of "ocaml.warning" (for instance, warnings 1, 2, 14, 29 and 50).

* "ocaml.warning" or "warnerror", with a string literal payload. Same as "ocaml.warning", for the `-warn-error` command-line option.
end

let impl : (module S) =
match repr with
| Immediate ->
  (module Int : S)
| Non_immediate ->
  (module Int64 : S)

include (val impl : S)
end

## 12.13 Extension nodes

(Introduced in OCaml 4.02, infix notations for constructs other than expressions added in 4.03, infix notation (`e1;%ext e2`) added in 4.04.)

Extension nodes are generic placeholders in the syntax tree. They are rejected by the type-checker and are intended to be “expanded” by external tools such as `-ppx` rewriters.

Extension nodes share the same notion of identifier and payload as attributes 12.12.

The first form of extension node is used for “algebraic” categories:

extension ::= [% attr-id attr-payload ]
expr ::= ...
 extension
 typexpr ::= ...
 extension
 pattern ::= ...
 extension
 module-expr ::= ...
 extension
 module-type ::= ...
 extension
class-expr ::= ...
 extension
class-type ::= ...
 extension

A second form of extension node can be used in structures and signatures, both in the module and object languages:
* "ocaml.alert" or "alert": see section 12.21.

* "ocaml.dePRECATED" or "deprecated": alias for the "deprecated" alert, see section 12.21.

* "ocaml.dePRECATEDmutable"" or "deprecated mutable". Can be applied to a mutable record label. If the label is later used to modify the field (with "expr.l <- expr"), the "deprecated" alert will be triggered. If the payload of the attribute is a string literal, the alert message includes this text.

* "ocaml.ppwarning" or "ppwarning", in any context, with a string literal payload. The text is reported as warning (22) by the compiler (currently, the warning location is the location of the string payload). This is mostly useful for preprocessors which need to communicate warnings to the user. This could also be used to mark explicitly some code location for further inspection.

* "ocaml.warn_on_literal_pattern" or "warn_on_literal_pattern" annotate constructors in type definition. A warning (52) is then emitted when this constructor is pattern matched with a constant literal as argument. This attribute denotes constructors whose argument is purely informative and may change in the future. Therefore, pattern matching on this argument with a constant literal is unreliable. For instance, all built-in exception constructors are marked as "warn_on_literal_pattern". Note that, due to an implementation limitation, this warning (52) is only triggered for single argument constructor.

* "ocaml.tailcall" or "tailcall" can be applied to function application in order to check that the call is tailcall optimized. If it is not the case, a warning (51) is emitted.

* "ocaml inline" or "inline" take either "never", "always" or nothing as payload on a function or functor definition. If no payload is provided, the default value is "always". This payload controls when applications of the annotated functions should be inlined.

* "ocaml.inlined" or "inlined" can be applied to any function or functor application to check
  that the call is inlined by the compiler. If the call is not inlined, a warning (55) is emitted.

* "ocaml.noalloc", "ocaml.unboxed" and "ocaml.untagged" or "noalloc", "unboxed" and "un-
tagged" can be used on external definitions to obtain finer control over the C-to-OCaml
interface. See 22.11 for more details.

* "ocaml.immediate" or "immediate" applied on an abstract type mark the type as having a non-pointer implementation (e.g. "int", "bool", "char" or enumerated types). Mutation of these immediate types does not activate the garbage collector's write barrier, which can significantly boost performance in programs relying heavily on mutable state.

* "ocaml.immediate64" or "immediate64" applied on an abstract type mark the type as hav-
ing a non-pointer implementation on 64 bit platforms. No assumption is made on other
platforms. In order to produce a type with the "immediate64" attribute, one must use
"Sys.Immediate64.Make" functor.

* ocaml.unboxed or unboxed can be used on a type definition if the type is a single-field record or a concrete type with a single constructor that has a single argument. It tells the compiler
<table><tr><td>item-extension</td><td>::=</td><td>[% attr-id attr-payload ]</td></tr><tr><td>definition</td><td>::=</td><td>...</td></tr><tr><td></td><td>|</td><td>item-extension</td></tr><tr><td>specification</td><td>::=</td><td>...</td></tr><tr><td></td><td>|</td><td>item-extension</td></tr><tr><td>class-field-spec</td><td>::=</td><td>...</td></tr><tr><td></td><td>|</td><td>item-extension</td></tr><tr><td>class-field</td><td>::=</td><td>...</td></tr><tr><td></td><td>|</td><td>item-extension</td></tr></table>

An infix form is available for extension nodes when the payload is of the same kind (expression with expression, pattern with pattern ...).

Examples:

```
let%foo x = 2 in x + 1     === [%foo let x = 2 in x + 1]
begin%foo ... end          === [%foo begin ... end]
x ;%foo 2                   === [%foo x; 2]
module%foo M = ..          === [%foo module M = ... ]
val%foo x : t              === [%foo: val x : t]
```

When this form is used together with the infix syntax for attributes, the attributes are considered to apply to the payload:

```
fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@bar] ];
```

An additional shorthand `let%foo x in ...` is available for convenience when extension nodes are used to implement binding operators (See 12.23.4).

Furthermore, quoted strings `{|...|}` can be combined with extension nodes to embed foreign syntax fragments. Those fragments can be interpreted by a preprocessor and turned into OCaml code without requiring escaping quotes. A syntax shortcut is available for them:

```
{%foo|...|}          === [%foo{|...|}]
let x = {%foo|...|}  === let x = [%foo{|...|}]
let y = {%foo bar|...|bar} === let y = [%foo{bar|...|bar}]
```

For instance, you can use `{%sql|...|}` to represent arbitrary SQL statements – assuming you have a ppx-rewriter that recognizes the `%sql` extension.

Note that the word-delimited form, for example `{sql|...|sql}`, should not be used for signaling that an extension is in use. Indeed, the user cannot see from the code whether this string literal has different semantics than they expect. Moreover, giving semantics to a specific delimiter limits the freedom to change the delimiter to avoid escaping issues.
to optimize the representation of the type by removing the block that represents the record or
the constructor (i.e. a value of this type is physically equal to its argument). In the case of
GADTs, an additional restriction applies: the argument must not be an existential variable,
represented by an existential type variable, or an abstract type constructor applied to an
existential type variable.

* `ocaml.boxed` or `boxed` can be used on type definitions to mean the opposite of `ocaml.unboxed`: keep the unoptimized representation of the type. When there is no annotation, the default is currently `boxed` but it may change in the future.

* `ocaml.local` or `local` take either `never`, `always`, `maybe` or nothing as payload on a function definition. If no payload is provided, the default is `always`. The attribute controls an optimization which consists in compiling a function into a static continuation. Contrary to inlining, this optimization does not duplicate the function's body. This is possible when all references to the function are full applications, all sharing the same continuation (for instance, the returned value of several branches of a pattern matching). `never` disables the optimization, `always` asserts that the optimization applies (otherwise a warning 55 is emitted) and `maybe` lets the optimization apply when possible (this is the default behavior when the attribute is not specified). The optimization is implicitly disabled when using the bytecode compiler in debug mode (-g), and for functions marked with an `ocaml inline always` or `ocaml.unrolled` attribute which supersede `ocaml.local`.

* `ocaml.poll` or `poll` with an `error` payload on a function definition emits an error whenever the compiler inserts a runtime polling point in the body of the annotated function.

* `ocaml atomic` or `atomic` on a record field definition, marks this record field as atomic. See 9.7.2 for more details.

module X = struct
    [@@warning "+9"] (* locally enable warning 9 in this structure *)
...
end
[@@deprecated "Please use module 'Y' instead."]

let x = begin[@warning "+9"] [...] end

type t = A | B
[@@deprecated "Please use type 's' instead."]

let fires_warning_22 x =
assert (x >= 0) [@ppwarning "TODO: remove this later"]

Warning 22 [preprocessor]: TODO: remove this later

let rec is_a_tail_call = function
| [] -> ()
| _ :: q -> (is_a_tail_call[@tailcall]) q
### 12.13.1 Built-in extension nodes

(Introduced in OCaml 4.03)

Some extension nodes are understood by the compiler itself:

* "ocaml.extension_constructor" or "extension_constructor" take as payload a constructor from an extensible variant type (see 12.14) and return its extension constructor slot.

```ocaml
type t = ..
type t += X of int | Y of string
let x = [%extension_constructor X]
let y = [%extension_constructor Y]

# x <> y;;
- : bool = true
```

## 12.14 Extensible variant types

(Introduced in OCaml 4.02)

```ocaml
type-representation ::= ...
                       | = ..

specification     ::= ...
                       | type [type-params] typeconstr type-extension-spec

definition        ::= ...
                       | type [type-params] typeconstr type-extension-def

type-extension-spec ::= += [private] [|] constr-decl {| constr-decl}
type-extension-def  ::= += [private] [|] constr-def {| constr-def}

constr-def         ::= constr-decl
                       | constr-name = constr
```

Extensible variant types are variant types which can be extended with new variant constructors. Extensible variant types are defined using `+=`. New variant constructors are added using `+=`.

```ocaml
module Expr = struct

type attr = ..

type attr += Str of string

type attr +=
    | Int of int
    | Float of float

end
```
```h
let rec not_aAnimalCall = function
  | [] -> []
  | x :: q -> x :: (not_aAnimalCall[@tailcall]) q
```

```
Warning 51 [wrong-tailcall-expectation]: expected tailcall
```

```h
let f x = x [@@inline]
```

```h
let () = (f[@inlined]) ()
```

```h
type fragile =
  | Int of int [@warn_on_literal_pattern]
  | String of string [@warn_on_literal_pattern]
```

```h
let fragile_match_1 = function
  | Int 0 -> ()
  | _ -> ()
```

```
Warning 52 [fragile-literal-pattern]: Code should not depend on the actual
values of this constructor's arguments.
They are only for information and may change in future versions.
(see manual section 13.5.3)
```

```h
val fragile_match_1 : fragile -> unit = <fun>
```

```h
let fragile_match_2 = function
  | String "constant" -> ()
  | _ -> ()
```

```
Warning 52 [fragile-literal-pattern]: Code should not depend on the actual
values of this constructor's arguments.
They are only for information and may change in future versions.
(see manual section 13.5.3)
```

```h
val fragile_match_2 : fragile -> unit = <fun>
```

```h
module Immediate: sig
  type t [@@immediate]
  val x: t ref
end = struct
  type t = A | B
  let x = ref A
end
```

```h
module Int_or_int64 : sig
  type t [@@immediate64]
  val zero : t
  val one : t
  val add : t -> t -> t
end = struct
```
Pattern matching on an extensible variant type requires a default case to handle unknown variant constructors:

```kotlin
let to_string = function
  | Expr.Str s -> s
  | Expr.Int i -> Int.to_string i
  | Expr FLOAT f -> string_of_float f
  | _ -> "?"
```

A preexisting example of an extensible variant type is the built-in `exn` type used for exceptions. Indeed, exception constructors can be declared using the type extension syntax:

```kotlin
type exn += Exc of int
```

Extensible variant constructors can be rebound to a different name. This allows exporting variants from another module.

```kotlin
# let not_in_scope = Str "Foo";
Error: Unbound constructor Str

type Expr.attr += Str = Expr.Str

# let now_works = Str "foo";
val now_works : Expr.attr = Expr.Str "foo"
```

Extensible variant constructors can be declared `private`. As with regular variants, this prevents them from being constructed directly by constructor application while still allowing them to be de-structured in pattern-matching.

```kotlin
module B : sig
  type Expr.attr += private Bool of int
  val bool : bool -> Expr.attr
end = struct
  type Expr.attr += Bool of int
  let bool p = if p then Bool 1 else Bool 0
end

# let inspection_works = function
  | B Bool p -> (p = 1)
  | _ -> true;

val inspection_works : Expr.attr -> bool = <fun>

# let construction_is_forbidden = B Bool 1;
Error: Cannot use private constructor Bool to create values of type Expr.attr
```

## 12.14.1 Private extensible variant types

(Introduced in OCaml 4.06)

```
type-representation ::= ...
                       | = private ..
```
include Sys.Immediate64.Make(Int)(Int64)

module type S = sig
  val zero : t
  val one : t
  val add : t -> t -> t
end

let impl : (module S) =
match repr with
| Immediate ->
  (module Int : S)
| Non_immediate ->
  (module Int64 : S)

include (val impl : S)
end

## 12.13 Extension nodes

(Introduced in OCaml 4.02, infix notations for constructs other than expressions added in 4.03, infix notation (`e1;%ext e2`) added in 4.04.)

Extension nodes are generic placeholders in the syntax tree. They are rejected by the type-checker and are intended to be “expanded” by external tools such as `-ppx` rewriters.

Extension nodes share the same notion of identifier and payload as attributes 12.12.

The first form of extension node is used for “algebraic” categories:
Extensible variant types can be declared **private**. This prevents new constructors from being declared directly, but allows extension constructors to be referred to in interfaces.

```pascal
module Msg : sig
    type t = private ..
    module MkConstr (X : sig type t end) : sig
        type t += C of X.t
end
end = struct
    type t = ..
    module MkConstr (X : sig type t end) = struct
        type t += C of X.t
end
end
```

## 12.15 Generative functors

(Introduced in OCaml 4.02)

```
module-expr ::= ...
               | functor () -> module-expr
               | module-expr ()

definition ::= ...
               | module module-name { ( module-name : module-type ) | () } [: module-type]
                         = module-expr

module-type ::= ...
               | [functor] () -> module-type

specification ::= ...
                   | module module-name { ( module-name : module-type ) | () } : module-type
```

A generative functor takes a unit () argument. In order to use it, one must necessarily apply it to this unit argument, ensuring that all type components in the result of the functor behave in a generative way, i.e. they are different from types obtained by other applications of the same functor. This is equivalent to taking an argument of signature `sig end`, and always applying to `struct end`, but not to some defined module (in the latter case, applying twice to the same module would return identical types).

As a side-effect of this generativity, one is allowed to unpack first-class modules in the body of generative functors.

## 12.16 Extension-only syntax

(Introduced in OCaml 4.02.2, extended in 4.03)
extension ::= [% attr-id attr-payload ]

expr ::= ...
 extension

typexpr ::= ...
 extension

pattern ::= ...
 extension

module-expr ::= ...
 extension

module-type ::= ...
 extension

class-expr ::= ...
 extension

class-type ::= ...
 extension

A second form of extension node can be used in structures and signatures, both in the module and object languages:

item-extension ::= [%% attr-id attr-payload ]

definition ::= ...
 item-extension

specification ::= ...
 item-extension

class-field-spec ::= ...
 item-extension

class-field ::= ...
 item-extension

An infix form is available for extension nodes when the payload is of the same kind (expression with expression, pattern with pattern ...).

Examples:

let%foo x = 2 in x + 1 === [%foo let x = 2 in x + 1]

begin%foo ... end === [%foo begin ... end]

x ;%foo 2 === [%foo x; 2]

module%foo M = .. === [%%foo module M = ... ]

val%foo x : t === [%%foo: val x : t]
Some syntactic constructions are accepted during parsing and rejected during type checking. These syntactic constructions can therefore not be used directly in vanilla OCaml. However, -ppx rewriters and other external tools can exploit this parser leniency to extend the language with these new syntactic constructions by rewriting them to vanilla constructions.

## 12.16.1 Extension operators

(Introduced in OCaml 4.02.2, extended to unary operators in OCaml 4.12.0)

**infix-symbol**

::= ...

| # {operator-char} # {operator-char | #}

**prefix-symbol**

::= ...

| (? | ~ | !) {operator-char} # {operator-char | #}

There are two classes of operators available for extensions: infix operators with a name starting with a `#` character and containing more than one `#` character, and unary operators with a name (starting with a `?`, `~`, or `!` character) containing at least one `#` character.

For instance:

```
# let infix x y = x##y;;
```

```
Error: '##' is not a valid value identifier.
```

```
# let prefix x = !#x;;
```

```
Error: '!#' is not a valid value identifier.
```

Note that both `##` and `!#` must be eliminated by a ppx rewriter to make this example valid.

## 12.16.2 Extension literals

(Introduced in OCaml 4.03)

**float-literal**

::= ...
| [-] (0...9) {0...9 | _} [. {0...9 | _}] [(e | E) [+ | -] (0...9) {0...9 | _}] [g...z | G...Z]
| [-] (0x | 0X) (0...9 | A...F | a...f) {0...9 | A...F | a...f | _}
| [. {0...9 | A...F | a...f | _}] [(p | P) [+ | -] (0...9) {0...9 | _}] [g...z | G...Z]

**int-literal**

| [-] (0...9) {0...9 | _} [g...z | G...Z]
| [-] (0x | 0X) (0...9 | A...F | a...f) {0...9 | A...F | a...f | _} [g...z | G...Z]
| [-] (0o | 0O) (0...7) {0...7 | _} [g...z | G...Z]
| [-] (0b | 0B) (0...1) {0...1 | _} [g...z | G...Z]

Int and float literals followed by an one-letter identifier in the range `[g..z | G..Z]` are extension-only literals.
When this form is used together with the infix syntax for attributes, the attributes are considered to apply to the payload:

fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@bar]];

An additional shorthand `let%foo x in ...` is available for convenience when extension nodes are used to implement binding operators (See 12.23.4).

Furthermore, quoted strings `{|...|}` can be combined with extension nodes to embed foreign syntax fragments. Those fragments can be interpreted by a preprocessor and turned into OCaml code without requiring escaping quotes. A syntax shortcut is available for them:

{%foo|...|}          === [%foo{|...|}]
let x = {%foo|...|}    === let x = [%foo{|...|}]
let y = {%foo bar|...|bar} === let y = [%foo{bar|...|bar}]

For instance, you can use `{%sql|...|}` to represent arbitrary SQL statements – assuming you have a ppx-rewriter that recognizes the `%sql` extension.

Note that the word-delimited form, for example `{sql|...|sql}`, should not be used for signaling that an extension is in use. Indeed, the user cannot see from the code whether this string literal has different semantics than they expect. Moreover, giving semantics to a specific delimiter limits the freedom to change the delimiter to avoid escaping issues.

### 12.13.1 Built-in extension nodes

(Introduced in OCaml 4.03)

Some extension nodes are understood by the compiler itself:

* `ocaml.extension_constructor` or `extension_constructor` extensions take as payload a constructor from an extensible variant type (see 12.14) and return its extension constructor slot.

type t = ..
type t += X of int | Y of string
let x = [%extension_constructor X]
let y = [%extension_constructor Y]

# x <> y;
- : bool = true

* `ocaml atomic.loc` or `atomic.loc` extensions take as payload an OCaml expression denoting an atomic location. See 9.7.2 for more details.

## 12.14 Extensible variant types

(Introduced in OCaml 4.02)
## 12.17 Inline records

(Introduced in OCaml 4.03)

```
constr-args ::= ...
| record-decl
```

The arguments of sum-type constructors can now be defined using the same syntax as records. Mutable and polymorphic fields are allowed. GADT syntax is supported. Attributes can be specified on individual fields.

Syntactically, building or matching constructors with such an inline record argument is similar to working with a unary constructor whose unique argument is a declared record type. A pattern can bind the inline record as a pseudo-value, but the record cannot escape the scope of the binding and can only be used with the dot-notation to extract or modify fields or to build new constructor values.

``` OCaml
type t =
  | Point of {width: int; mutable x: float; mutable y: float}
  | Other
```

``` OCaml
let v = Point {width = 10; x = 0.; y = 0.}
```

``` OCaml
let scale l = function
  | Point p -> Point {p with x = l * . p.x; y = l * . p.y}
  | Other -> Other
```

``` OCaml
let print = function
  | Point {x; y; _} -> Printf printf "%f/%f" x y
  | Other -> ()
```

``` OCaml
let reset = function
  | Point p -> p.x <- 0.; p.y <- 0.
  | Other -> ()
```

``` OCaml
let invalid = function
  | Point p -> p
```

```
Error: This form is not allowed as the type of the inlined record could escape.
```

## 12.18 Documentation comments

(Introduced in OCaml 4.03)

Comments which start with `**` are treated specially by the compiler. They are automatically converted during parsing into attributes (see 12.12) to allow tools to process them as documentation.

Such comments can take three forms: *floating comments*, *item comments* and *label comments*. Any comment starting with `**` which does not match one of these forms will cause the compiler to emit warning 50.
```
type-representation ::= ...
                       | = ..
specification     ::= ...
                       | type [type-params] typeconstr type-extension-spec
definition        ::= ...
                       | type [type-params] typeconstr type-extension-def

type-extension-spec ::= += [private] [|] constr-decl { | constr-decl }
type-extension-def  ::= += [private] [|] constr-def { | constr-def }

constr-def         ::= constr-decl
                       | constr-name = constr
```

Extensible variant types are variant types which can be extended with new variant constructors. Extensible variant types are defined using `+=`. New variant constructors are added using `+=`.

```python
module Expr = struct

type attr = ..

type attr += Str of string

type attr +=
    | Int of int
    | Float of float
```

end

Pattern matching on an extensible variant type requires a default case to handle unknown variant constructors:

```python
let to_string = function
  | Expr.Str s -> s
  | Expr.Int i -> Int.to_string i
  | Expr FLOAT f -> string_of_float f
  | _ -> "?"
```

A preexisting example of an extensible variant type is the built-in `exn` type used for exceptions. Indeed, exception constructors can be declared using the type extension syntax:

```
type exn += Exc of int
```

Extensible variant constructors can be rebound to a different name. This allows exporting variants from another module.

```python
# let not_in_scope = Str "Foo";

Error: Unbound constructor Str

type Expr.attr += Str = Expr.Str

# let now_works = Str "foo";
```
Comments which start with ** are also used by the ocamldoc documentation generator (see 19). The three comment forms recognised by the compiler are a subset of the forms accepted by ocamldoc (see 19.2).

### 12.18.1 Floating comments

Comments surrounded by blank lines that appear within structures, signatures, classes or class types are converted into *floating-attributes*. For example:

```
type t = T
```

(*\*\* Now some definitions for [t] \*\*\*)

```
let mkT = T
```

will be converted to:

```
type t = T
```

```
[@@@ocaml.text " Now some definitions for [t] "]
```

```
let mkT = T
```

### 12.18.2 Item comments

Comments which appear *immediately before* or *immediately after* a structure item, signature item, class item or class type item are converted into *item-attributes*. Immediately before or immediately after means that there must be no blank lines, ;;, or other documentation comments between them. For example:

```
type t = T
```

(*\*\* A description of [t] \*\*\*)

or

(*\*\* A description of [t] \*\*\*)

```
type t = T
```

will be converted to:

```
type t = T
```

```
[@@ocaml.doc " A description of [t] "]
```

Note that, if a comment appears immediately next to multiple items, as in:

```
type t = T
```

(*\*\* An ambiguous comment \*\*\*)

```
type s = S
```

then it will be attached to both items:

```
type t = T
```

```
[@@ocaml.doc " An ambiguous comment "]
```

```
type s = S
```

```
[@@ocaml.doc " An ambiguous comment "]
```

and the compiler will emit warning 50.
```pascal
val now_works : Expr.attr = Expr.Str "foo"
```

Extensible variant constructors can be declared **private**. As with regular variants, this prevents them from being constructed directly by constructor application while still allowing them to be de-structured in pattern-matching.

```pascal
module B : sig
    type Expr.attr += private Bool of int
    val bool : bool -> Expr.attr
end = struct
    type Expr.attr += Bool of int
    let bool p = if p then Bool 1 else Bool 0
end
```

```pascal
# let inspection_works = function
| B Bool p -> (p = 1)
| _ -> true;;
val inspection_works : Expr.attr -> bool = <fun>
```

```pascal
# let construction_is_forbidden = B Bool 1;;
```

```
Error: Cannot use private constructor Bool to create values of type Expr.attr
```

## 12.14.1 Private extensible variant types

(Introduced in OCaml 4.06)

```
type-representation ::= ...
                       | = private ..
```

Extensible variant types can be declared **private**. This prevents new constructors from being declared directly, but allows extension constructors to be referred to in interfaces.

```pascal
module Msg : sig
    type t = private ..
    module MkConstr (X : sig type t end) : sig
        type t += C of X.t
end
end = struct
    type t = ..
    module MkConstr (X : sig type t end) = struct
        type t += C of X.t
end
end
```
## 12.15 Generative functors

(Introduced in OCaml 4.02)

module-expr ::= ...
| functor () -> module-expr
| module-expr ()

definition ::= ...
| module module-name { ( module-name : module-type ) | () } [ : module-type ]
= module-expr

module-type ::= ...
| [functor] () -> module-type

specification ::= ...
| module module-name { ( module-name : module-type ) | () } : module-type

A generative functor takes a unit () argument. In order to use it, one must necessarily apply it to this unit argument, ensuring that all type components in the result of the functor behave in a generative way, i.e. they are different from types obtained by other applications of the same functor. This is equivalent to taking an argument of signature `sig end`, and always applying to `struct end`, but not to some defined module (in the latter case, applying twice to the same module would return identical types).

As a side-effect of this generativity, one is allowed to unpack first-class modules in the body of generative functors.

## 12.16 Extension-only syntax

(Introduced in OCaml 4.02.2, extended in 4.03)

Some syntactic constructions are accepted during parsing and rejected during type checking. These syntactic constructions can therefore not be used directly in vanilla OCaml. However, `-ppx` rewriters and other external tools can exploit this parser leniency to extend the language with these new syntactic constructions by rewriting them to vanilla constructions.

### 12.16.1 Extension operators

(Introduced in OCaml 4.02.2, extended to unary operators in OCaml 4.12.0)

infix-symbol ::= ...
| # {operator-char} # {operator-char | #}

prefix-symbol ::= ...
| (? | ~ | !) {operator-char} # {operator-char | #}
whilst:

type t = T of string

(** Attaches to T not t *)

(** Attaches to t *)

will be converted to:

type t = T of string [@ocaml.doc " Attaches to T not t "]
[@@ocaml.doc " Attaches to t "]

In the absence of meaningful comment on the last constructor of a type, an empty comment (**) can be used instead:

type t = T of string

(**)

(** Attaches to t *)

will be converted directly to

type t = T of string

[@@ocaml.doc " Attaches to t "]

## 12.19 Extended indexing operators

(Introduced in 4.06)

dot-ext ::=
| dot-operator-char {operator-char}

dot-operator-char ::= ! | ? | core-operator-char | % | :

expr ::= ...
| expr . [module-path .] dot-ext (( expr ) | [ expr ] | { expr }) [<- expr ]

operator-name ::= ...
| . dot-ext (( ) | [] | { }) [←]

This extension provides syntactic sugar for getting and setting elements for user-defined indexed types. For instance, we can define python-like dictionaries with

module Dict = struct
include Hashtbl
let ( .%{} ) tabl index = find tabl index
let ( .%{}<- ) tabl index value = add tabl index value
end
let dict =
    let dict = Dict.create 10 in
let () =
    dict Dict.%{"one"} <- 1;
let open Dict in
There are two classes of operators available for extensions: infix operators with a name starting with a `#` character and containing more than one `#` character, and unary operators with a name (starting with a `?`, `~`, or `!` character) containing at least one `#` character.

For instance:

```hml
# let infix x y = x##y;;
```

```
Error: ## is not a valid value identifier.
```

```hml
# let prefix x = !#x;;
```

```
Error: !# is not a valid value identifier.
```

Note that both `##` and `!#` must be eliminated by a ppx rewriter to make this example valid.

## 12.16.2 Extension literals

(Introduced in OCaml 4.03)

<table><tr><td><strong>float-literal</strong></td><td>::= ...<br>| [-] (0...9) {0...9|}_ [. {0...9|}_] [(e|E) [ + | - ] (0...9) {0...9|}_] [g...z|G...Z]<br>| [-] (0x|0X) (0...9|A...F|a...f) {0...9|A...F|a...f|}_<br>| [. {0...9|A...F|a...f|}_] [(p|P) [ + | - ] (0...9) {0...9|}_] [g...z|G...Z]</td></tr></table>

<table><tr><td><strong>int-literal</strong></td><td>::= ...<br>| [-] (0...9) {0...9|}_ [g...z|G...Z]<br>| [-] (0x|0X) (0...9|A...F|a...f) {0...9|A...F|a...f|}_ [g...z|G...Z]<br>| [-] (0o|0O) (0...7) {0...7|}_ [g...z|G...Z]<br>| [-] (0b|0B) (0...1) {0...1|}_ [g...z|G...Z]</td></tr></table>

Int and float literals followed by an one-letter identifier in the range `[g.. z | G.. Z]` are extension-only literals.

## 12.17 Inline records

(Introduced in OCaml 4.03)

```
constr-args ::= ...
| record-decl
```

The arguments of sum-type constructors can now be defined using the same syntax as records. Mutable and polymorphic fields are allowed. GADT syntax is supported. Attributes can be specified on individual fields.

Syntactically, building or matching constructors with such an inline record argument is similar to working with a unary constructor whose unique argument is a declared record type. A pattern can bind the inline record as a pseudo-value, but the record cannot escape the scope of the binding and can only be used with the dot-notation to extract or modify fields or to build new constructor values.
```python
dict.%{"two"} <- 2 in
dict

# dict Dict.%{"one"};;
- : int = 1

# let open Dict in dict.%{"two"};;
- : int = 2
```

### 12.19.1 Multi-index notation

```
expr ::= ...
       | expr . [module-path .] dot-ext ( expr {; expr}^+ ) [<- expr]
       | expr . [module-path .] dot-ext [ expr {; expr}^+ ] [<- expr]
       | expr . [module-path .] dot-ext { expr {; expr}^+ } [<- expr]

operator-name ::= ...
                   | . dot-ext ((;..) | [;..] | {...}) [<-]
```

Multi-index are also supported through a second variant of indexing operators

```python
let (.%[;..]) = Bigarray.Genarray.get
let (.%{;..}) = Bigarray.Genarray.get
let (.%(;;..)) = Bigarray.Genarray.get
```

which is called when an index literals contain a semicolon separated list of expressions with two and more elements:

```python
let sum x y = x.%[1;2;3] + y.%[1;2]
(* is equivalent to *)
let sum x y = (.%[;..]) x [|1;2;3|] + (.%[;..]) y [|1;2|]
```

In particular this multi-index notation makes it possible to uniformly handle indexing Genarray and other implementations of multidimensional arrays.

```python
module A = Bigarray.Genarray
let (.%{;..}) = A.get
let (.%{;..}<-) = A.set
let (.%{ }) a k = A.get a [|k|]
let (.%{ }<-) a k x = A.set a [|k|] x
let syntax_compare vec mat t3 t4 =
    vec.%{0} = A.get vec [|0|]
&& mat.%{0;0} = A.get mat [|0;0|]
&& t3.%{0;0;0} = A.get t3 [|0;0;0|]
&& t4.%{0;0;0;0} = t4.{0,0,0,0}
```

Beware that the differentiation between the multi-index and single index operators is purely syntactic: multi-index operators are restricted to index expressions that contain one or more semicolons ;. For instance,

```python
let pair vec mat = vec.%{0}, mat.%{0;0}
```
```h
type t =
  | Point of {width: int; mutable x: float; mutable y: float}
  | Other
```

```h
let v = Point {width = 10; x = 0.; y = 0.}
```

```h
let scale l = function
  | Point p -> Point {p with x = l * . p.x; y = l * . p.y}
  | Other -> Other
```

```h
let print = function
  | Point {x; y; _} -> Printf printf "%f/%f" x y
  | Other -> ()
```

```h
let reset = function
  | Point p -> p.x <- 0.; p.y <- 0.
  | Other -> ()
```

```h
let invalid = function
  | Point p -> p
```

```
Error: This form is not allowed as the type of the inlined record could escape.
```

## 12.18 Documentation comments

(Introduced in OCaml 4.03)

Comments which start with `**` are treated specially by the compiler. They are automatically converted during parsing into attributes (see 12.12) to allow tools to process them as documentation.

Such comments can take three forms: *floating comments*, *item comments* and *label comments*. Any comment starting with `**` which does not match one of these forms will cause the compiler to emit warning 50.

Comments which start with `**` are also used by the ocamldoc documentation generator (see 19). The three comment forms recognised by the compiler are a subset of the forms accepted by ocamldoc (see 19.2).

### 12.18.1 Floating comments

Comments surrounded by blank lines that appear within structures, signatures, classes or class types are converted into *floating-attributes*. For example:

```h
type t = T
```

(** Now some definitions for [t] *)

```h
let mkT = T
```

will be converted to:
is equivalent to

let pair vec mat = (.%{ }) vec 0, (.%{;..}) mat [|0;0|]

Notice that in the vec case, we are calling the single index operator, (.%{}) , and not the multi-index variant, (.{;..}) . For this reason, it is expected that most users of multi-index operators will need to define conjointly a single index variant

let (.%{;..}) = A.get

let (.%{ }) a k = A.get a [|k|]

to handle both cases uniformly.

12.20 Empty variant types

(Introduced in 4.07.0)

type-representation ::= ... | = |

This extension allows user to define empty variants. Empty variant type can be eliminated by refutation case of pattern matching.

type t = |

let f (x: t) = match x with _ -> .

12.21 Alerts

(Introduced in 4.08)

Since OCaml 4.08, it is possible to mark components (such as value or type declarations) in signatures with “alerts” that will be reported when those components are referenced. This generalizes the notion of “deprecated” components which were previously reported as warning 3. Those alerts can be used for instance to report usage of unsafe features, or of features which are only available on some platforms, etc.

Alert categories are identified by a symbolic identifier (a lowercase identifier, following the usual lexical rules) and an optional message. The identifier is used to control which alerts are enabled, and which ones are turned into fatal errors. The message is reported to the user when the alert is triggered (i.e. when the marked component is referenced).

The ocaml.alert or alert attribute serves two purposes: (i) to mark component with an alert to be triggered when the component is referenced, and (ii) to control which alert names are enabled. In the first form, the attribute takes an identifier possibly followed by a message. Here is an example of a value declaration marked with an alert:

module U: sig

val fork: unit -> bool

[@alert unix "This function is only available under Unix."]

end
```kotlin
type t = T
```

```
[@@@ocaml.text " Now some definitions for [t] "]
```

```kotlin
let mkT = T
```

### 12.18.2 Item comments

Comments which appear *immediately before* or *immediately after* a structure item, signature item, class item or class type item are converted into *item-attributes*. Immediately before or immediately after means that there must be no blank lines, `;`, `;`, or other documentation comments between them. For example:

```kotlin
type t = T
```

*(** A description of [t] *)*

or

*(** A description of [t] *)*

```kotlin
type t = T
```

will be converted to:

```kotlin
type t = T
```

```
[@@ocaml.doc " A description of [t] "]
```

Note that, if a comment appears immediately next to multiple items, as in:

```kotlin
type t = T
```

*(** An ambiguous comment *)*

```kotlin
type s = S
```

then it will be attached to both items:

```kotlin
type t = T
```

```
[@@ocaml.doc " An ambiguous comment "]
```

```kotlin
type s = S
```

```
[@@ocaml.doc " An ambiguous comment "]
```

and the compiler will emit warning 50.

### 12.18.3 Label comments

Comments which appear *immediately after* a labelled argument, record field, variant constructor, object method or polymorphic variant constructor are converted into *attributes*. Immediately after means that there must be no blank lines or other documentation comments between them. For example:

```kotlin
type t1 = lbl:int (** Labelled argument *) -> unit
```

```kotlin
type t2 = {
    fld: int; (** Record field *)
    fld2: float;
}
```
Here `unix` is the identifier for the alert. If this alert category is enabled, any reference to `U.fork` will produce a message at compile time, which can be turned or not into a fatal error.

And here is another example as a floating attribute on top of an `*.mli` file (i.e. before any other non-attribute item) or on top of an `*.ml` file without a corresponding interface file, so that any reference to that unit will trigger the alert:

```
[@@@alert unsafe "This module is unsafe!"]
```

Controlling which alerts are enabled and whether they are turned into fatal errors is done either through the compiler's command-line option `-alert <spec>` or locally in the code through the `alert` or `ocaml.alert` attribute taking a single string payload `<spec>`. In both cases, the syntax for `<spec>` is a concatenation of items of the form:

* `+id` enables alert `id`.

* `-id` disables alert `id`.

* `++id` turns alert `id` into a fatal error.

* `--id` turns alert `id` into non-fatal mode.

* `@id` equivalent to `++id+id` (enables `id` and turns it into a fatal-error)

As a special case, if `id` is `all`, it stands for all alerts.

Here are some examples:

```
(* Disable all alerts, reenables just unix (as a soft alert) and window (as a fatal-error), for the rest of the current structure *)

[@@@alert "-all--all+unix@window"]
```

```
...
```

```
let x =
    (* Locally disable the window alert *)
    begin[@alert "-window"]
```

```
...
```

```
end
```

Before OCaml 4.08, there was support for a single kind of deprecation alert. It is now known as the deprecated alert, but legacy attributes to trigger it and the legacy ways to control it as warning 3 are still supported. For instance, passing `-w +3` on the command-line is equivalent to `-alert +deprecated`, and:

```
val x: int
[@@ocaml.dePRECATED "Please do something else"]
```

is equivalent to:

```
val x: int
[@@ocaml.alert deprecated "Please do something else"]
```
## 12.22 Generalized open statements

(Introduced in 4.08)

definition ::= ...
| open module-expr
| open! module-expr

specification ::= ...
| open extended-module-path
| open! extended-module-path

expr ::= ...
| let open module-expr in expr
| let open! module-expr in expr

This extension makes it possible to open any module expression in module structures and expressions. A similar mechanism is also available inside module types, but only for extended module paths (e.g. `F(X).G(Y)`).

For instance, a module can be constrained when opened with

module M = struct let x = 0 let hidden = 1 end
open (M:sig val x: int end)
let y = hidden

Error: Unbound value hidden

Another possibility is to immediately open the result of a functor application

let sort (type x) (x:x list) =
let open Set.Make(struct type t = x let compare=compare end) in
  elements (of_list x)
val sort : 'x list -> 'x list = <fun>

Going further, this construction can introduce local components inside a structure,

module M = struct
  let x = 0
  open! struct
    let x = 0
    let y = 1
  end
  let w = x + y
end

module M : sig val x : int val w : int end

One important restriction is that types introduced by `open struct... end` cannot appear in the signature of the enclosing structure, unless they are defined equal to some non-local type. So:

module M = struct
  open struct type 'a t = 'a option = None | Some of 'a end
(** Attaches to t *)

will be converted directly to

type t = T of string

[@@ocaml.doc " Attaches to t "]

12.19 Extended indexing operators

(Introduced in 4.06)

dot-ext ::=

| dot-operator-char {operator-char}

dot-operator-char ::= ! | ? | core-operator-char | % | :

expr ::= ...

| expr . [module-path .] dot-ext (( expr ) | [ expr ] | { expr }) [ <- expr ]

operator-name ::= ...

| . dot-ext (( ) | [] | { }) [ <- ]

This extension provides syntactic sugar for getting and setting elements for user-defined indexed
types. For instance, we can define python-like dictionaries with

module Dict = struct
  include Hashtbl
  let ( .%{} ) tabl index = find tabl index
  let ( .%{}<- ) tabl index value = add tabl index value
end

let dict =
  let dict = Dict.create 10 in
  let () =
    dict Dict.%{"one"} <- 1;
    let open Dict in
    dict.%{"two"} <- 2 in
  dict
# dict Dict.%{"one"};;
- : int = 1

# let open Dict in dict.%{"two"};;
- : int = 2
let x : int t = Some 1

end

module M : sig val x : int option end

is OK, but:

module M = struct

open struct type t = A end

let x = A

end

Error: The type t introduced by this open appears in the signature.
The value x has no valid type if t is hidden.

is not because x cannot be given any type other than t, which only exists locally. Although the
above would be OK if x too was local:

module M: sig end = struct

open struct

type t = A

end

...

open struct let x = A end

...

end

module M : sig end

Inside signatures, extended opens are limited to extended module paths,

module type S = sig

module F: sig end -> sig type t end

module X: sig end

open F(X)

val f: t

end

module type S =

sig

module F : sig end -> sig type t end

module X : sig end

val f : F(X) . t

end

and not

open struct type t = int end

In those situations, local substitutions(see 12.7.2) can be used instead.

Beware that this extension is not available inside class definitions:

class c =

let open Set.Make(Int) in

...
## 12.19.1 Multi-index notation

expr ::= ...
| expr . [module-path .] dot-ext ( expr {; expr}^+ ) [<- expr]
| expr . [module-path .] dot-ext [ expr {; expr}^+ ] [<- expr]
| expr . [module-path .] dot-ext { expr {; expr}^+ } [<- expr]

operator-name ::= ...
| . dot-ext ((;..) | [;..] | {...}) [<-]

Multi-index are also supported through a second variant of indexing operators

let (.%[;..]) = Bigarray.Genarray.get
let (.%{;..}) = Bigarray.Genarray.get
let (.(%(..)) = Bigarray.Genarray.get

which is called when an index literals contain a semicolon separated list of expressions with two and more elements:

let sum x y = x.%[1;2;3] + y.%[1;2]
(* is equivalent to *)
let sum x y = (.%[;..]) x [|1;2;3|] + (.%[;..]) y [|1;2|]

In particular this multi-index notation makes it possible to uniformly handle indexing Genarray and other implementations of multidimensional arrays.

module A = Bigarray.Genarray
let (.%{;..}) = A.get
let (.%{;..}< - ) = A.set
let (.%{ }) a k = A.get a [|k|]
let (.%{ }< - ) a k x = A.set a [|k|] x
let syntax_compare vec mat t3 t4 =
  vec.%{0} = A.get vec [|0|]
&& mat.%{0;0} = A.get mat [|0;0|]
&& t3.%{0;0;0} = A.get t3 [|0;0;0|]
&& t4.%{0;0;0;0} = t4.{0,0,0,0}

Beware that the differentiation between the multi-index and single index operators is purely syntactic: multi-index operators are restricted to index expressions that contain one or more semicolons ;. For instance,

let pair vec mat = vec.%{0}, mat.%{0;0}
is equivalent to

let pair vec mat = (.%{ }) vec 0, (.%{;..}) mat [|0;0|]

Notice that in the vec case, we are calling the single index operator, (.%{ }) , and not the multi-index variant, (.{;..}) . For this reason, it is expected that most users of multi-index operators will need to define conjointly a single index variant

let (.%{;..}) = A.get
let (.%{ }) a k = A.get a [|k|]
to handle both cases uniformly.
## 12.23 Binding operators

(Introduced in 4.08.0)

```
let-operator ::=
| let (core-operator-char | <) {dot-operator-char}

and-operator ::=
| and (core-operator-char | <) {dot-operator-char}

operator-name ::= ...
| let-operator
| and-operator

letop-binding ::= pattern = expr
| value-name

expr ::= ...
| let-operator letop-binding {and-operator letop-binding} in expr
```

Binding operators offer syntactic sugar to expose library functions under (a variant of) the familiar syntax of standard keywords. Currently supported “binding operators” are `let<op>` and `and<op>`, where `<op>` is an operator symbol, for example `and+$`.

Binding operators were introduced to offer convenient syntax for working with monads and applicative functors; for those, we propose conventions using operators `*` and `+` respectively. They may be used for other purposes, but one should keep in mind that each new unfamiliar notation introduced makes programs harder to understand for non-experts. We expect that new conventions will be developed over time on other families of operator.

### 12.23.1 Examples

Users can define *let operators*:

```
let ( let* ) o f =
match o with
| None -> None
| Some x -> f x

let return x = Some x
val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = <fun>
val return : 'a -> 'a option = <fun>
```

and then apply them using this convenient syntax:

```
let find_and_sum tbl k1 k2 =
let* x1 = Hashtbl.find_opt tbl k1 in
let* x2 = Hashtbl.find_opt tbl k2 in
return (x1 + x2)
```
## 12.20 Empty variant types

(Introduced in 4.07.0)

$$ \mathit{type-representation} ::= \dots \\ | = | $$

This extension allows user to define empty variants. Empty variant type can be eliminated by refutation case of pattern matching.

```hkl
type t = |
let f (x: t) = match x with _ -> .
```

## 12.21 Alerts

(Introduced in 4.08)

Since OCaml 4.08, it is possible to mark components (such as value or type declarations) in signatures with “alerts” that will be reported when those components are referenced. This generalizes the notion of “deprecated” components which were previously reported as warning 3. Those alerts can be used for instance to report usage of unsafe features, or of features which are only available on some platforms, etc.

Alert categories are identified by a symbolic identifier (a lowercase identifier, following the usual lexical rules) and an optional message. The identifier is used to control which alerts are enabled, and which ones are turned into fatal errors. The message is reported to the user when the alert is triggered (i.e. when the marked component is referenced).

The `ocaml.alert` or `alert` attribute serves two purposes: (i) to mark component with an alert to be triggered when the component is referenced, and (ii) to control which alerts are enabled.

### 12.21.1 Marking a component

When marking a component, the attribute takes an identifier possibly followed by a message. Here is an example of a value declaration marked with an alert:

```hkl
module U: sig
  val fork: unit -> bool
  [@@alert unix "This function is only available under Unix."]
end
```

Here `unix` is the identifier for the alert. If this alert category is enabled, any reference to `U.fork` will produce a message at compile time, which can be turned or not into a fatal error.

For other structure or signature components, the syntax is as follows:

```hkl
module type Sig = sig
  val v: int [@@alert name]
end
```

```hkl
let v [@alert name] = 1
let `A (v [@alert name]) = `A 1
```
```h
val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = <fun>
```

which is equivalent to this expanded form:

```h
let find_and_sum tbl k1 k2 =
  ( let* ) (Hashtbl.find_opt tbl k1)
  (fun x1 ->
    ( let* ) (Hashtbl.find_opt tbl k2)
    (fun x2 -> return (x1 + x2)))
val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = <fun>
```

Users can also define *and* operators:

```h
module ZipSeq = struct

type 'a t = 'a Seq.t

open Seq

let rec return x =
  fun () -> Cons(x, return x)

let rec prod a b =
  fun () ->
    match a (), b () with
    | Nil, _ | _ , Nil -> Nil
    | Cons(x, a), Cons(y, b) -> Cons((x, y), prod a b)

let ( let+ ) f s = map s f
let ( and+ ) a b = prod a b

end

module ZipSeq :
  sig
    type 'a t = 'a Seq.t
    val return : 'a -> 'a Seq.t
    val prod : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
    val ( let+ ) : 'a Seq.t -> ('a -> 'b) -> 'b Seq.t
    val ( and+ ) : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
  end
```

to support the syntax:

```h
open ZipSeq

let sum3 z1 z2 z3 =
  let+ x1 = z1
  and+ x2 = z2
  and+ x3 = z3 in
  x1 + x2 + x3
```
external e : int -> int = "c_function" [@@alert name]

type t1 = A | B [@@alert name]

(* N.B.: this only alerts on use of "t1", not uses of the constructors "A" and "B". So let x = A wouldn't alert, so long as you don't write down its type. *)

type t2 = A | B [alert name]

(* Alerts on use of "B", but not "A" nor "t2". Note the single "@". *)

type t3 = { a : int; b : int [alert name] }

(* Alerts on use of "b", but not "a" nor "t3". Note the single "@". *)

exception E of int [alert name]

(* Alerts on use of "E". Note the single "@". *)

module M = struct end [@@alert name]

module type S = sig end [@@alert name]

class c1 = object end [@@alert name]

class type c2 = object end [@@alert name]

When the typer coerces a signature with alerts to a signature with different alerts:

module M : sig

val x : int

val y : int [@@alert name]

end = struct

let x [@alert name] = 0

let y = 1

end

any alert that isn't passed through, i.e. the alert on x here, gets triggered.

Finally, to alert when the module corresponding to a file is referenced, a floating attribute can be written at the top of the ".mli" file (i.e. before any other non-attribute item), or the top of the ".ml" file if there is no ".mli" file:

[@@@alert unsafe "This module is unsafe!"]

## 12.21.2 Controlling which alerts are enabled

Controlling which alerts are enabled and whether they are turned into fatal errors is done either through the compiler's command-line option `-alert <spec>` or locally in the code through the `alert` or `ocaml.alert` attribute taking a single string payload `<spec>`. In both cases, the syntax for `<spec>` is a concatenation of items of the form:

* `+id` enables alert `id`.

* `-id` disables alert `id`.

* `++id` turns alert `id` into a fatal error.
```hkl
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>
```

which is equivalent to this expanded form:

```hkl
open ZipSeq
let sum3 z1 z2 z3 =
  ( let+ ) (( and+ ) (( and+ ) z1 z2) z3)
  (fun ((x1, x2), x3) -> x1 + x2 + x3)
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>
```

## 12.23.2 Conventions

An applicative functor should provide a module implementing the following interface:

```hkl
module type Applicative_syntax = sig
    type 'a t
    val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
    val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t
end
```

where `(let+)` is bound to the `map` operation and `(and+)` is bound to the monoidal product operation.

A monad should provide a module implementing the following interface:

```hkl
module type Monad_syntax = sig
    include Applicative_syntax
    val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
    val ( and* ) : 'a t -> 'b t -> ('a * 'b) t
end
```

where `(let*)` is bound to the `bind` operation, and `(and*)` is also bound to the monoidal product operation.

## 12.23.3 General desugaring rules

The form

```hkl
let<op0>
    x1 = e1
and<op1>
    x2 = e2
and<op2>
    x3 = e3
in e
```

desugars into

```hkl
( let<op0> )
(( and<op2> )
(( and<op1> )
```
* `--id` turns alert `id` into non-fatal mode.

* `@id` equivalent to `++id+id` (enables `id` and turns it into a fatal-error)

As a special case, if `id` is all, it stands for all alerts.

Here are some examples:

```
(* Disable all alerts, reenables just unix (as a soft alert) and window
(as a fatal-error), for the rest of the current structure *)
```

```
[@@alert "-all--all+unix@window"]
```

...

```h.lisp
let x =
  (* Locally disable the window alert *)
  begin[@alert "-window"]
```

...

end

### 12.21.3 Shorthand syntax for deprecation

Before OCaml 4.08, there was support for a single kind of deprecation alert. It is now known as the deprecated alert, but legacy attributes to trigger it and the legacy ways to control it as warning 3 are still supported. For instance, passing `-w +3` on the command-line is equivalent to `-alert +deprecated`, and:

```h.lisp
val x: int
[@@ocaml.dePRECATED "Please do something else"]
is equivalent to:
```

```h.lisp
val x: int
[@@ocaml.alert deprecated "Please do something else"]
```

## 12.22 Generalized open statements

(Introduced in 4.08)

```
definition ::= ...
               | open module-expr
               | open! module-expr
```

```
specification ::= ...
                   | open extended-module-path
                   | open! extended-module-path
```

```
expr ::= ...
        | let open module-expr in expr
        | let open! module-expr in expr
```
e1
e2)
e3)
 fun((x1, x2), x3) -> e)

This of course works for any number of nested and-operators. One can express the general rule by repeating the following simplification steps:

* The first and-operator in

let<op0> x1 = e1 and<op1> x2 = e2 and... in e

can be desugared into a function application

let<op0> (x1, x2) = ( and<op1> ) e1 e2 and... in e.

* Once all and-operators have been simplified away, the let-operator in

let<op> x1 = e1 in e

can be desugared into an application

( let<op> ) e1 (fun x1 -> e).

Note that the grammar allows mixing different operator symbols in the same binding (<op0>, <op1>, <op2> may be distinct), but we strongly recommend APIs where let-operators and and-operators working together use the same symbol.

### 12.23.4 Short notation for variable bindings (let-punning)

(Introduced in 4.13.0)

When the expression being bound is a variable, it can be convenient to use the shorthand notation `let+ x in ...`, which expands to `let+ x = x in ...`. This notation, also known as let-punning, allows the `sum3` function above can be written more concisely as:

open ZipSeq
let sum3 z1 z2 z3 =
  let+ z1 and+ z2 and+ z3 in
  z1 + z2 + z3
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>

This notation is also supported for extension nodes, expanding `let%foo x in ...` to `let%foo x = x in ...`. However, to avoid confusion, this notation is not supported for plain `let` bindings.
This extension makes it possible to open any module expression in module structures and expressions. A similar mechanism is also available inside module types, but only for extended module paths (e.g. `F(X)`. `G(Y)`).

For instance, a module can be constrained when opened with

```python
module M = struct let x = 0 let hidden = 1 end
open (M:sig val x: int end)
let y = hidden
```

```
Error: Unbound value hidden
```

Another possibility is to immediately open the result of a functor application

```python
let sort (type x) (x:x list) =
    let open Set.Make(struct type t = x let compare=compare end) in
    elements (of_list x)
val sort : 'x list -> 'x list = <fun>
```

Going further, this construction can introduce local components inside a structure,

```python
module M = struct
    let x = 0
    open! struct
        let x = 0
        let y = 1
    end
    let w = x + y
end
module M : sig val x : int val w : int end
```

One important restriction is that types introduced by `open struct... end` cannot appear in the signature of the enclosing structure, unless they are defined equal to some non-local type. So:

```python
module M = struct
    open struct type 'a t = 'a option = None | Some of 'a end
    let x : int t = Some 1
end
module M : sig val x : int option end
```

is OK, but:

```python
module M = struct
    open struct type t = A end
    let x = A
end
```

```
Error: The type t introduced by this open appears in the signature.
The value x has no valid type if t is hidden.
```

is not because x cannot be given any type other than t, which only exists locally. Although the above would be OK if x too was local:
## 12.24 Effect handlers

(Introduced in 5.0)

**Note:** Effect handlers in OCaml 5.0 should be considered experimental. Effect handlers are exposed in the standard library's Effect [28.16] module as a thin wrapper around their implementation in the runtime. They are not supported as a language feature with new syntax. You can rely on them to build non-local control-flow abstractions such as user-level threading that do not expose the effect handler primitives to the user. Expect breaking changes in the future.

Effect handlers are a mechanism for modular programming with user-defined effects. Effect handlers allow the programmers to describe computations that perform effectful operations, whose meaning is described by handlers that enclose the computations. Effect handlers are a generalization of exception handlers and enable non-local control-flow mechanisms such as resumable exceptions, lightweight threads, coroutines, generators and asynchronous I/O to be composably expressed. In this tutorial, we shall see how some of these mechanisms can be built using effect handlers.

### 12.24.1 Basics

To understand the basics, let us define an effect (that is, an operation) that takes an integer argument and returns an integer result. We name this effect `Xchg`.

```ocaml
open Effect
open Effect.Deep
```

```hl
type _ Effect.t += Xchg: int -> int t
let comp1 () = perform (Xchg 0) + perform (Xchg 1)
```

We declare the exchange effect `Xchg` by extending the pre-defined extensible variant type `Effect.t` with a new constructor `Xchg: int -> int t`. The declaration may be intuitively read as "the `Xchg` effect takes an integer parameter, and when this effect is performed, it returns an integer". The computation `comp1` performs the effect twice using the `perform` primitive and returns their sum.

We can handle the `Xchg` effect by implementing a handler that always returns the successor of the offered value:

```hl
try_with comp1 ()
  { effc = fun (type a) (eff: a t) ->
    match eff with
    | Xchg n -> Some (fun (k: (a, _ ) continuation) ->
                        continue k (n+1))
    | _ -> None }
- : int = 3
```

`try_with` runs the computation `comp1 ()` under an effect handler that handles the `Xchg` effect. As mentioned earlier, effect handlers are a generalization of exception handlers. Similar to exception handlers, when the computation performs the `Xchg` effect, the control jumps to the corresponding handler. However, unlike exception handlers, the handler is also provided with the delimited continuation `k`, which represents the suspended computation between the point of `perform` and this handler.
```python
module M: sig end = struct
    open struct
type t = A
end

...
open struct let x = A end

...
end

module M : sig end
```

Inside signatures, extended opens are limited to extended module paths,

```python
module type S = sig
    module F: sig end -> sig type t end
    module X: sig end
    open F(X)
    val f: t
end

module type S =
    sig
        module F : sig end -> sig type t end
        module X : sig end
        val f : F(X).t
    end

and not

open struct type t = int end
```

In those situations, local substitutions(see 12.7.2) can be used instead.

Beware that this extension is not available inside class definitions:

```python
class c =
    let open Set.Make(Int) in
    ...
```

## 12.23 Binding operators

(Introduced in 4.08.0)
The handler uses the `continue` primitive to resume the suspended computation with the successor of the offered value. In this example, the computation `comp1` performs `Xchg 0` and `Xchg 1` and receives the values `1` and `2` from the handler respectively. Hence, the whole expression evaluates to `3`.

It is useful to note that we must use a locally abstract type (`type a`) in the effect handler. The type `Effect.t` is a GADT, and the effect declarations may have different type parameters for different effects. The type parameter `a` in the type `a Effect.t` represents the type of the value returned when performing the effect. From the fact that `eff` has type `a Effect.t` and from the fact that `Xchg n` has type `int Effect.t`, the type-checker deduces that `a` must be `int`, which is why we are allowed to pass the integer value `n+1` as an argument to `continue k`.

Another point to note is that the catch-all case `| _ -> None` is necessary when handling effects. This case may be intuitively read as “forward the unhandled effects to the outer handler”.

In this example, we use the *deep* version of the effect handlers here as opposed to the *shallow* version. A deep handler monitors a computation until the computation terminates (either normally or via an exception), and handles all of the effects performed (in sequence) by the computation. In contrast, a shallow handler monitors a computation until either the computation terminates or the computation performs one effect, and it handles this single effect only. In situations where they are applicable, deep handlers are usually preferred. An example that utilises shallow handlers is discussed later in 12.24.12.

## 12.24.2 Concurrency

The expressive power of effect handlers comes from the delimited continuation. While the previous example immediately resumed the computation, the computation may be resumed later, running some other computation in the interim. Let us extend the previous example and implement message-passing concurrency between two concurrent computations using the `Xchg` effect. We call these concurrent computations *tasks*.

A task either is in a suspended state or is completed. We represent the task status as follows:

```haskell
type 'a status =
    Complete of 'a
  | Suspended of {msg: int; cont: (int, 'a status) continuation}
```

A task either is complete, with a result of type `'a`, or is suspended with the message `msg` to send and the continuation `cont`. The type `(int, 'a status) continuation` says that the suspended computation expects an `int` value to resume and returns a `'a status` value when resumed.

Next, we define a `step` function that executes one step of computation until it completes or suspends:

```haskell
let step (f : unit -> 'a) () : 'a status =
    match_with f ()
    { retc = (fun v -> Complete v);
     exnc = raise;
     effc = fun (type a) (eff: a t) ->
                match eff with
                | Xchg msg -> Some (fun (cont: (a,_) continuation) ->
                                          Suspended {msg; cont})
                | _ -> None }
```
```
let-operator ::=
| let (core-operator-char | <) {dot-operator-char}

and-operator ::=
| and (core-operator-char | <) {dot-operator-char}

operator-name ::= ...
| let-operator
| and-operator

letop-binding ::= pattern = expr
| value-name

expr ::= ...
| let-operator letop-binding {and-operator letop-binding} in expr
```

Binding operators offer syntactic sugar to expose library functions under (a variant of) the familiar syntax of standard keywords. Currently supported “binding operators” are `let<op>` and `and<op>`, where `<op>` is an operator symbol, for example `and+$`.

Binding operators were introduced to offer convenient syntax for working with monads and applicative functors; for those, we propose conventions using operators `*` and `+` respectively. They may be used for other purposes, but one should keep in mind that each new unfamiliar notation introduced makes programs harder to understand for non-experts. We expect that new conventions will be developed over time on other families of operator.

## 12.23.1 Examples

Users can define *let operators*:

```
let ( let* ) o f =
match o with
| None -> None
| Some x -> f x

let return x = Some x
val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = <fun>
val return : 'a -> 'a option = <fun>
```

and then apply them using this convenient syntax:

```
let find_and_sum tbl k1 k2 =
let* x1 = Hashtbl.find_opt tbl k1 in
let* x2 = Hashtbl.find_opt tbl k2 in
return (x1 + x2)
val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = <fun>
```

which is equivalent to this expanded form:
The argument to the step function, f, is a computation that can perform an Xchg effect and returns a result of type 'a. The step function itself returns a 'a status value.

In the step function, we use the match_with primitive. Like try_with, match_with primitive installs an effect handler. However, unlike try_with, where only the effect case effc is provided, match_with expects the handlers for the value (retc) and exceptional (exnc) return cases. In fact, try_with can be defined using match_with as follows:

let try_with f v {effc} = match_with f v {retc = Fun.id; exnc = raise; effc}.

In the step function,

* Case retc: If the computation returns with a value v, we return Complete v.

* Case exnc: If the computation raises an exception, then the handler raises the same exception.

* Case effc: If the computation performs the effect Xchg msg with the continuation cont, then we return Suspended{msg; cont}. Thus, in this case, the continuation cont is not immediately invoked by the handler; instead, it is stored in a data structure for later use.

Since the step function handles the Xchg effect, step f is a computation that does not perform the Xchg effect. It may however perform other effects. Moreover, since we are using deep handlers, the continuation cont stored in the status does not perform the Xchg effect.

We can now write a simple scheduler that runs a pair of tasks to completion:

let rec run_both a b =
match a (), b () with
| Complete va, Complete vb -> (va, vb)
| Suspended {msg = m1; cont = k1},
  Suspended {msg = m2; cont = k2} ->
    run_both (fun () -> continue k1 m2)
    (fun () -> continue k2 m1)
| _ -> failwith "Improper synchronization"

Both of the tasks may run to completion, or both may offer to exchange a message. In the latter case, each computation receives the value offered by the other computation. The situation where one computation offers an exchange while the other computation terminates is regarded as a programmer error, and causes the handler to raise an exception

We can now define a second computation that also exchanges two messages:

let comp2 () = perform (Xchg 21) * perform (Xchg 21)

Finally, we can run the two computations together:

run_both (step comp1) (step comp2)
- : int * int = (42, 0)

The computation comp1 offers the values 0 and 1 and in exchange receives the values 21 and 21, which it adds, producing 42. The computation comp2 offers the values 21 and 21 and in exchange receives the values 0 and 1, which it multiplies, producing 0. The communication between the two computations is programmed entirely inside run_both. Indeed, the definitions of comp1 and comp2, alone, do not assign any meaning to the Xchg effect.
```h
let find_and_sum tbl k1 k2 =
  ( let* ) (Hashtbl.find_opt tbl k1)
  (fun x1 ->
    ( let* ) (Hashtbl.find_opt tbl k2)
    (fun x2 -> return (x1 + x2)))
val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = <fun>
```

Users can also define *and operators*:

```h
module ZipSeq = struct

type 'a t = 'a Seq.t

open Seq

let rec return x =
  fun () -> Cons(x, return x)

let rec prod a b =
  fun () ->
    match a (), b () with
    | Nil, _ | _ , Nil -> Nil
    | Cons(x, a), Cons(y, b) -> Cons((x, y), prod a b)

let ( let+ ) f s = map s f
let ( and+ ) a b = prod a b
```

```h
end
module ZipSeq :
  sig
    type 'a t = 'a Seq.t
    val return : 'a -> 'a Seq.t
    val prod : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
    val ( let+ ) : 'a Seq.t -> ('a -> 'b) -> 'b Seq.t
    val ( and+ ) : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
  end
```

to support the syntax:

```h
open ZipSeq
let sum3 z1 z2 z3 =
  let+ x1 = z1
  and+ x2 = z2
  and+ x3 = z3 in
  x1 + x2 + x3
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>
```

which is equivalent to this expanded form:
### 12.24.3 User-level threads

Let us extend the previous example for an arbitrary number of tasks. Many languages such as `GHC` `Haskell` and `Go` provide user-level threads as a primitive feature implemented in the runtime system. With effect handlers, user-level threads and their schedulers can be implemented in `OCaml` itself. Typically, user-level threading systems provide a `fork` primitive to spawn off a new concurrent task and a `yield` primitive to yield control to some other task. Correspondingly, we shall declare two effects as follows:

```hml
type _ Effect.t += Fork : (unit -> unit) -> unit t
    | Yield : unit t
```

The `Fork` effect takes a chunk (a suspended computation, represented as a function of type `unit -> unit`) and returns a unit to the performer. The `Yield` effect is unparameterized and returns a unit when performed. Let us consider that a task performing an `Xchg` effect may match with any other task also offering to exchange a value.

We shall also define helper functions that simply perform these effects:

```hml
let fork f = perform (Fork f)
let yield () = perform Yield
let xchg v = perform (Xchg v)
```

A top-level `run` function defines the scheduler:

(* A concurrent round-robin scheduler *)

```hml
let run (main : unit -> unit) : unit =
    let exchanger = ref None in (* waiting exchanger *)
    let run_q = Queue.create () in (* scheduler queue *)
    let enqueue k v =
        let task () = continue k v in
        Queue.push task run_q
    in
    let dequeue () =
        if Queue.is_empty run_q then () (* done *)
        else begin
            let task = Queue.pop run_q in
            task ()
        end
    in
    let rec spawn (f : unit -> unit) : unit =
        match_with f () {
            retc = dequeue;
            exnc = (fun e ->
                      print_endline (Printexc.to_string e);
                      dequeue());
            effc = fun (type a) (eff : a t) ->
                      match eff with
                      | Yield -> Some (fun (k : (a, unit) continuation) ->
                                              enqueue k (); dequeue())
```
```hkl
open ZipSeq
let sum3 z1 z2 z3 =
  ( let+ ) (( and+ ) (( and+ ) z1 z2) z3)
  (fun ((x1, x2), x3) -> x1 + x2 + x3)
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>
```

## 12.23.2 Conventions

An applicative functor should provide a module implementing the following interface:

```hkl
module type Applicative_syntax = sig
    type 'a t
    val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
    val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t
end
```

where `(let+)` is bound to the `map` operation and `(and+)` is bound to the monoidal product operation.

A monad should provide a module implementing the following interface:

```hkl
module type Monad_syntax = sig
    include Applicative_syntax
    val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
    val ( and* ) : 'a t -> 'b t -> ('a * 'b) t
end
```

where `(let*)` is bound to the `bind` operation, and `(and*)` is also bound to the monoidal product operation.

## 12.23.3 General desugaring rules

The form

```hkl
let<op0>
    x1 = e1
and<op1>
    x2 = e2
and<op2>
    x3 = e3
in e
```

desugars into

```hkl
( let<op0> )
(( and<op2> )
(( and<op1> )
    e1
    e2)
    e3)
 fun ((x1, x2), x3) -> e)
```
```R
Fork f -> Some (fun (k : (a, unit) continuation) ->
    enqueue k (); spawn f)

Xchg n -> Some (fun (k : (int, unit) continuation) ->
    begin match !exchanger with
    | Some (n', k') ->
        exchanger := None; enqueue k' n; continue k n'
    | None -> exchanger := Some (n, k); dequeue ()
    end)

| _ -> None
}

in
spawn main
```

We use a mutable queue `run_q` to hold the scheduler queue. The FIFO queue enables round-robin scheduling of tasks in the scheduler. `enqueue` inserts tasks into the queue, and `dequeue` extracts tasks from the queue and runs them. The reference cell `exchanger` holds a (suspended) task offering to exchange a value. At any time, there is either zero or one suspended task that is offering an exchange.

The heavy lifting is done by the `spawn` function. The `spawn` function runs the given computation `f` in an effect handler. If `f` returns with a value (case `retc`), we dequeue and run the next task from the scheduler queue. If the computation `f` raises an exception (case `exnc`), we print the exception and run the next task from the scheduler.

The computation `f` may also perform effects. If `f` performs the `Yield` effect, the current task is suspended (inserted into the queue of ready tasks), and the next task from the scheduler queue is run. If the effect is `Fork f`, then the current task is suspended, and the new task `f` is executed immediately via a tail call to `spawn f`. Note that this choice to run the new task first is arbitrary. We could very well have chosen instead to insert the task for `f` into the ready queue and resumed `k` immediately.

If the effect is `Xchg`, then we first check whether there is a task waiting to exchange. If so, we enqueue the waiting task with the current value being offered and immediately resume the current task with the value being offered. If not, we make the current task the waiting exchanger, and run the next task from the scheduler queue.

Note that this scheduler code is not perfect – it can leak resources. We shall explain and fix this in the next section 12.24.4.

Now we can write a concurrent program that utilises the newly defined operations:

```R
open Printf

let _ = run (fun _ ->
    fork (fun _ ->
        printf "[t1] Sending 0\n";
        let v = xchg 0 in
        printf "[t1] received %d\n" v);
    fork (fun _ ->
        printf "[t2] Sending 1\n";
        let v = xchg 1 in
        printf "[t2] received %d\n" v))
```
This of course works for any number of nested and-operators. One can express the general rule by
repeating the following simplification steps:

* The first and-operator in

let<op0> x1 = e1 and<op1> x2 = e2 and... in e

can be desugared into a function application

let<op0> (x1, x2) = ( and<op1> ) e1 e2 and... in e.

* Once all and-operators have been simplified away, the let-operator in

let<op> x1 = e1 in e

can be desugared into an application

( let<op> ) e1 (fun x1 -> e).

Note that the grammar allows mixing different operator symbols in the same binding (<op0>, <op1>, <op2> may be distinct), but we strongly recommend APIs where let-operators and and-operators working together use the same symbol.

### 12.23.4 Short notation for variable bindings (let-punning)

(Introduced in 4.13.0)

When the expression being bound is a variable, it can be convenient to use the shorthand notation `let+ x in ...`, which expands to `let+ x = x in ...`. This notation, also known as let-punning, allows the `sum3` function above can be written more concisely as:

open ZipSeq
let sum3 z1 z2 z3 =
  let+ z1 and+ z2 and+ z3 in
  z1 + z2 + z3
val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = <fun>

This notation is also supported for extension nodes, expanding `let%foo x in ...` to `let%foo x = x in ...`. However, to avoid confusion, this notation is not supported for plain `let` bindings.

## 12.24 Effect handlers

(Introduced in 5.0. The syntax support for deep handlers was introduced in 5.3.)

pattern ::= ...
             | effect pattern, value-name
[t1] Sending 0
[t2] Sending 1
[t2] received 0
[t1] received 1

Observe that the messages from the two tasks are interleaved. Notice also that the snippet above makes no reference to the effect handlers and is in direct style (no monadic operations). This example illustrates that, with effect handlers, the user code in a concurrent program can remain in simple direct style, and the use of effect handlers can be fully contained within the concurrency library implementation.

### 12.24.4 Resuming with an exception

In addition to resuming a continuation with a value, effect handlers also permit resuming by raising an effect at the point of perform. This is done with the help of the `discontinue` primitive. The `discontinue` primitive helps ensure that resources are always eventually deallocated, even in the presence of effects.

For example, consider the dequeue operation in the previous example reproduced below:

...

If the scheduler queue is empty, dequeue considers that the scheduler is done and returns to the caller. However, there may still be a task waiting to exchange a value (stored in the reference cell `exchanger`), which remains blocked forever! If the blocked task holds onto resources, these resources are leaked. For example, consider the following task:

```javascript
let leaky_task () =
  fork (fun _ ->
        let oc = open_out "secret.txt" in
        Fun.protect ~finally: (fun _ -> close_out oc) (fun _ ->
          output_value oc (xchg 0)))
```

The task writes the received message to the file `secret.txt`. It uses `Fun.protect` to ensure that the output channel `oc` is closed on both normal and exceptional return cases. Unfortunately, this is not sufficient. If the exchange effect `xchg 0` cannot be matched with an exchange effect performed by some other thread, then this task remains blocked forever. Thus, the output channel `oc` is never closed.

To avoid this problem, one must adhere to a simple discipline: every continuation must be eventually either continued or discontinued. Here, we use `discontinue` to ensure that the blocked task does not remain blocked forever. By discontinuing this task, we force it to terminate (with an exception):

```
exception Improper_synchronization
```

```javascript
let dequeue () =
  if Queue.is_empty run_q then begin
    match !exchanger with
```
Effect handlers are a mechanism for modular programming with user-defined effects. Effect handlers allow the programmers to describe *computations* that *perform* effectful *operations*, whose meaning is described by *handlers* that enclose the computations. Effect handlers are a generalization of exception handlers and enable non-local control-flow mechanisms such as resumable exceptions, lightweight threads, coroutines, generators and asynchronous I/O to be comosably expressed. In this tutorial, we shall see how some of these mechanisms can be built using effect handlers.

### 12.24.1 Basics

To understand the basics, let us define an effect (that is, an operation) that takes an integer argument and returns an integer result. We name this effect `Xchg`.

```python
open Effect
open Effect.Deep
```

```python
type _ Effect.t += Xchg: int -> int t
let comp1 () = perform (Xchg 0) + perform (Xchg 1)
```

We declare the exchange effect `Xchg` by extending the pre-defined extensible variant type `Effect.t` with a new constructor `Xchg: int -> int t`. The declaration may be intuitively read as “the `Xchg` effect takes an integer parameter, and when this effect is performed, it returns an integer”. The computation `comp1` performs the effect twice using the `perform` primitive and returns their sum.

We can handle the `Xchg` effect by implementing a handler that always returns the successor of the offered value:

```python
try comp1 () with
  | effect (Xchg n), k -> continue k (n+1)
- : int = 3
```

We run the computation `comp1()` under an effect handler that handles the `Xchg` effect with a continuation bound to `k`. Here `effect` is a keyword which signifies that the `Xchg n` pattern matches effects and not exceptions. As mentioned earlier, effect handlers are a generalization of exception handlers. Similar to exception handlers, when the computation performs the `Xchg` effect, the control jumps to the corresponding handler, and unhandled effects are forwarded to the outer handler. However, unlike exception handlers, the handler is also provided with the delimited continuation `k`, which represents the suspended computation between the point of `perform` and this handler.

The handler uses the `continue` primitive to resume the suspended computation with the successor of the offered value. In this example, the computation `comp1` performs `Xchg 0` and `Xchg 1` and receives the values `1` and `2` from the handler respectively. Hence, the whole expression evaluates to `3`.

In this example, we use the *deep* version of the effect handlers here as opposed to the *shallow* version. A deep handler monitors a computation until the computation terminates (either normally or via an exception), and handles all of the effects performed (in sequence) by the computation. In contrast, a shallow handler monitors a computation until either the computation terminates or the computation performs one effect, and it handles this single effect only. In situations where they are applicable, deep handlers are usually preferred. An example that utilises shallow handlers is discussed later in 12.24.13.
```python
| None -> () (* done *)
| Some (n, k) ->
    exchanger := None;
    discontinue k Improper_synchronization
end else (Queue.pop run_q) ()
```

When the scheduler queue is empty and there is a blocked exchanger thread, the dequeue function discontinues the blocked thread with an `Improper_synchronization` exception. This exception is raised at the blocked `xchg` function call, which causes the `finally` block to be run and closes the output channel `oc`. From the point of view of the user, it seems as though the function call `xchg 0` raises the exception `Improper_synchronization`.

### 12.24.5 Control inversion

When it comes to performing traversals on a data structure, there are two fundamental ways depending on whether the producer or the consumer has the control over the traversal. For example, in `List.iter` f 1, the producer `List.iter` has the control and pushes the element to the consumer f who processes them. On the other hand, the `Seq[28.48]` module provides a mechanism similar to delayed lists where the consumer controls the traversal. For example, `Seq.forever Randombool` returns an infinite sequence of random bits where every bit is produced (on demand) when queried by the consumer.

Naturally, producers such as `List.iter` are easier to write in the former style. The latter style is ergonomically better for the consumer since it is preferable and more natural to be in control. To have the best of both worlds, we would like to write a producer in the former style and automatically convert it to the latter style. The conversion can be written *once and for all* as a library function, thanks to effect handlers. Let us name this function `invert`. We will first look at how to use the `invert` function before looking at its implementation details. The type of this function is given below:

```python
val invert : iter:(( 'a -> unit ) -> unit ) -> 'a Seq.t
```

The `invert` function takes an `iter` function (a producer that pushes elements to the consumer) and returns a sequence (where the consumer has the control). For example,

```python
let lst_iter = Fun flip List.iter [1;2;3]
val lst_iter : (int -> unit) -> unit = <fun>
```

is an `iter` function with type `(int -> unit) -> unit`. The expression `lst_iter f` pushes the elements 1, 2 and 3 to the consumer `f`. For example,

```python
lst_iter (fun i ->FORMAT printf "%d\n" i)
1
2
3
- : unit = ()
```

The expression `invert lst_iter` returns a sequence that allows the consumer to traverse the list on demand. For example,

```python
let s = invert ~iter:lst_iter
let next = Seq.to_dispenser s;;
```
### 12.24.2 Concurrency

The expressive power of effect handlers comes from the delimited continuation. While the previous example immediately resumed the computation, the computation may be resumed later, running some other computation in the interim. Let us extend the previous example and implement message-passing concurrency between two concurrent computations using the `Xchg` effect. We call these concurrent computations *tasks*.

A task either is in a suspended state or is completed. We represent the task status as follows:

```haskell
type 'a status =
    Complete of 'a
  | Suspended of {msg: int; cont: (int, 'a status) continuation}
```

A task either is complete, with a result of type `'a`, or is suspended with the message `msg` to send and the continuation `cont`. The type `(int, 'a status) continuation` says that the suspended delimited computation expects an `int` value to resume and returns a value of type `'a status` when resumed.

Next, we define a `step` function that executes one step of computation until it completes or suspends:

```haskell
let step (f : unit -> 'a) () : 'a status =
    match f () with
    | v -> Complete v
    | effect (Xchg msg), cont -> Suspended {msg; cont}
```

The argument to the `step` function, `f`, is a computation that can perform an `Xchg` effect and returns a result of type `'a`. The `step` function itself returns a value of type `'a status`. Similar to exception patterns in a `match ... with` expression (11.6.1), OCaml also supports `effect` patterns. Here, we pattern match the result of running the computation `f`. If the computation returns with a value `v`, we return `Complete v`. Instead, if the computation performs the effect `Xchg msg` with the continuation `cont`, then we return `Suspended {msg; cont}`. In this case, the continuation `cont` is not immediately invoked by the handler; instead, it is stored in a data structure for later use.

Since the `step` function handles the `Xchg` effect, `step f` is a computation that does not perform the `Xchg` effect. It may however perform other effects. Moreover, since we are using deep handlers, the continuation `cont` stored in the status does not perform the `Xchg` effect.

We can now write a simple scheduler that runs a pair of tasks to completion:

```haskell
let rec runBoth a b =
    match a (), b () with
    | Complete va, Complete vb -> (va, vb)
    | Suspended {msg = m1; cont = k1},
      Suspended {msg = m2; cont = k2} ->
      runBoth (fun () -> continue k1 m2)
        (fun () -> continue k2 m1)
    | _ -> failwith "Improper synchronization"
```

Both of the tasks may run to completion, or both may offer to exchange a message. In the latter case, each computation receives the value offered by the other computation. The situation where one computation offers an exchange while the other computation terminates is regarded as a programmer error, and causes the handler to raise an exception.
```h
val s : int Seq.t = <fun>
val next : unit -> int option = <fun>
```

```h
next();;
- : int option = Some 1
```

```h
next();;
- : int option = Some 2
```

```h
next();;
- : int option = Some 3
```

```h
next();;
- : int option = None
```

We can use the same `invert` function on any `iter` function. For example,

```h
let s = invert ~iter:(Fun flip String.iter "OCaml")
let next = Seq.to_dispenser s;;
val s : char Seq.t = <fun>
val next : unit -> char option = <fun>
```

```h
next();;
- : char option = Some '0'
```

```h
next();;
- : char option = Some 'C'
```

```h
next();;
- : char option = Some 'a'
```

```h
next();;
- : char option = Some 'm'
```

```h
next();;
- : char option = Some 'l'
```

```h
next();;
- : char option = None
```

### 12.24.6 Implementing control inversion

The implementation of the `invert` function is given below:

```h
let invert (type a) ~(iter : (a -> unit) -> unit) : a Seq.t =
  let module M = struct
    type _ Effect.t += Yield : a -> unit t
  end in
  let yield v = perform (M.Yield v) in
```
We can now define a second computation that also exchanges two messages:

```hkl
let comp2 () = perform (Xchg 21) * perform (Xchg 21)
```

Finally, we can run the two computations together:

```hkl
runBoth (step comp1) (step comp2)
```

```hkl
- : int * int = (42, 0)
```

The computation `comp1` offers the values 0 and 1 and in exchange receives the values 21 and 21, which it adds, producing 42. The computation `comp2` offers the values 21 and 21 and in exchange receives the values 0 and 1, which it multiplies, producing 0. The communication between the two computations is programmed entirely inside `runBoth`. Indeed, the definitions of `comp1` and `comp2`, alone, do not assign any meaning to the `Xchg` effect.

### 12.24.3 User-level threads

Let us extend the previous example for an arbitrary number of tasks. Many languages such as `GHC` Haskell and `Go` provide user-level threads as a primitive feature implemented in the runtime system. With effect handlers, user-level threads and their schedulers can be implemented in `OCaml` itself. Typically, user-level threading systems provide a `fork` primitive to spawn off a new concurrent task and a `yield` primitive to yield control to some other task. Correspondingly, we shall declare two effects as follows:

```hkl
type _ Effect.t += Fork : (unit -> unit) -> unit t
```

```hkl
| Yield : unit t
```

The `Fork` effect takes a `thunk` (a suspended computation, represented as a function of type `unit -> unit`) and returns a `unit` to the performer. The `Yield` effect is unparameterized and returns a `unit` when performed. Let us consider that a task performing an `Xchg` effect may match with any other task also offering to exchange a value.

We shall also define helper functions that simply perform these effects:

```hkl
let fork f = perform (Fork f)
```

```hkl
let yield () = perform Yield
```

```hkl
let xchg v = perform (Xchg v)
```

A top-level `run` function defines the scheduler:

```
(* A concurrent round-robin scheduler *)
```

```hkl
let run (main : unit -> unit) : unit =
    let exchanger : (int * (int, unit) continuation) option ref =
        ref None (* waiting exchanger *)
```

```hkl
in
```

```hkl
let run_q = Queue.create () in (* scheduler queue *)
```

```hkl
let enqueue k v =
    let task () = continue k v in
    Queue.push task run_q
```

```hkl
in
```

```hkl
let dequeue () =
    if Queue.is_empty run_q then () (* done *)
    else begin
```
```h
fun () -> match_with iter yield
{ retc = (fun _ -> Seq Nil);
  excn = raise;
  effc = fun (type b) (eff : b Effect.t) ->
    match eff with
    | M.Yield v -> Some (fun (k: (b,_) continuation) ->
                          Seq.Cons (v, continue k))
    | _ -> None }
```

The `invert` function declares an effect `Yield` that takes the element to be yielded as a parameter. The `yield` function performs the `Yield` effect. The lambda abstraction `fun () -> ...` delays all action until the first element of the sequence is demanded. Once this happens, the computation `iter yield` is executed under an effect handler. Every time the `iter` function pushes an element to the `yield` function, the computation is interrupted by the `Yield` effect. The `Yield` effect is handled by returning the value `Seq.Cons(v,continue k)` to the consumer. The consumer gets the element `v` as well as the suspended computation, which in the consumer's eyes is just the tail of sequence.

When the consumer demands the next element from the sequence (by applying it to `()`), the continuation `k` is resumed. This allows the computation `iter yield` to make progress, until it either yields another element or terminates normally. In the latter case, the value `Seq Nil` is returned, indicating to the consumer that the iteration is over.

It is important to note that the sequence returned by the `invert` function is *ephemeral* (as defined by the `Seq[28.48]` module) i.e., the sequence must be used at most once. Additionally, the sequence must be fully consumed (i.e., used at least once) so as to ensure that the captured continuation is used linearly.

### 12.24.7 Semantics

In this section, we shall see the semantics of effect handlers with the help of examples.

### 12.24.8 Nesting handlers

Like exception handlers, effect handlers can be nested.

```h
type _ Effect.t += E : int t
               | F : string t

let foo () = perform F

let bar () =
  try_with foo ()
  { effc = fun (type a) (eff: a t) ->
    match eff with
    | E -> Some (fun (k: (a,_) continuation) ->
                   failwith "impossible")
    | _ -> None }

let baz () =
```
```hsharp
let task = Queue.pop run_q in
  task ()
end

in
let rec spawn (f : unit -> unit) : unit =
  match f () with
  | () -> dequeue ()
  | exception e ->
      print_endline (Printexc.to_string e);
      dequeue ()
  | effect Yield, k -> enqueue k (); dequeue ()
  | effect (Fork f), k -> enqueue k (); spawn f
  | effect (Xchg n), k ->
      begin match !exchanger with
        | Some (n', k') -> exchanger := None; enqueue k' n; continue k n'
        | None -> exchanger := Some (n, k); dequeue ()
      end
in
spawn main
```

We use a mutable queue `run_q` to hold the scheduler queue. The FIFO queue enables round-robin scheduling of tasks in the scheduler. `enqueue` inserts tasks into the queue, and `dequeue` extracts tasks from the queue and runs them. The reference cell `exchanger` holds a (suspended) task offering to exchange a value. At any time, there is either zero or one suspended task that is offering an exchange.

The heavy lifting is done by the `spawn` function. The `spawn` function runs the given computation `f` in an effect handler. If `f` returns with unit value, we dequeue and run the next task from the scheduler queue. If the computation `f` raises any exception, we print the exception to the standard output and run the next task from the scheduler.

The computation `f` may also perform effects. If `f` performs the `Yield` effect, the current task is suspended (inserted into the queue of ready tasks), and the next task from the scheduler queue is run. If the effect is `Fork f`, then the current task is suspended, and the new task `f` is executed immediately via a tail call to `spawn f`. Note that this choice to run the new task first is arbitrary. We could very well have chosen instead to insert the task for `f` into the ready queue and resumed `k` immediately.

If the effect is `Xchg`, then we first check whether there is a task waiting to exchange. If so, we enqueue the waiting task with the current value being offered and immediately resume the current task with the value being offered. If not, we make the current task the waiting exchanger, and run the next task from the scheduler queue.

Now we can write a concurrent program that utilises the newly defined operations:

```hsharp
open Printf

let _ = run (fun _ ->
  fork (fun _ ->
    printf "[t1] Sending 0\n";
    let v = xchg 0 in
```
```h
try_with bar ()
{
    effc = fun (type a) (eff: a t) ->
                match eff with
                | F -> Some (fun (k: (a,_)) continuation) ->
                  continue k "Hello, world!")
                | _ -> None }
```

In this example, the computation `foo` performs `F`, the inner handler handles only `E` and the outer handler handles `F`. The call to `baz` returns `Hello, world!`.

```h
baz ()
- : string = "Hello, world!"
```

## 12.24.9 Fibers

It is useful to know a little bit about the implementation of effect handlers to appreciate the design choices and their performance characteristics. Effect handlers are implemented with the help of runtime-managed, dynamically growing segments of stack called *fibers*. The program stack in OCaml is a linked list of such fibers.

A new fiber is allocated for evaluating the computation enclosed by an effect handler. The fiber is freed when the computation returns to the caller either normally by returning a value or by raising an exception.

At the point of `perform` in `foo` in the previous example, the program stack looks like this:

```
+------+      +------+      +------+
|      |      |      |      |
| baz  |<--| bar  |<--| foo |
|      |      |      |      |
|      |      |      |      |
+------+      +------+      +------+
|      |      |      | <-- stack_pointer |
+------+
```

The two links correspond to the two effect handlers in the program. When the effect `F` is handled in `baz`, the program state looks as follows:

```
+------+
|      |
+------+
|      |      |      |      | +--+
| baz  |      | bar  |<--| foo |<--|k|
|      |      |      |      | +--+
+------+ <-- stack_pointer +------+      +------+
```

The delimited continuation `k` is an object on the heap that refers to the segment of the stack that corresponds to the suspended computation. Capturing a continuation does not involve copying stack frames. When the continuation is resumed, the stack is restored to the previous state by linking together the segment pointed to by `k` to the current stack. Since neither continuation capture nor resumption requires copying stack frames, suspending the execution using `perform` and resuming it using either `continue` or `discontinue` are fast.
```python
printf "[t1] received %d\n" v);
fork (fun _ ->
    printf "[t2] Sending 1\n";
    let v = xchg 1 in
    printf "[t2] received %d\n" v))
[t1] Sending 0
[t2] Sending 1
[t2] received 0
[t1] received 1
```

Observe that the messages from the two tasks are interleaved. Notice also that the snippet above makes no reference to the effect handlers and is in direct style (no monadic operations). This example illustrates that, with effect handlers, the user code in a concurrent program can remain in simple direct style, and the use of effect handlers can be fully contained within the concurrency library implementation.

### 12.24.4 Resuming with an exception

In addition to resuming a continuation with a value, effect handlers also permit resuming by raising an effect at the point of perform. This is done with the help of the `discontinue` primitive. The `discontinue` primitive helps ensure that resources are always eventually deallocated, even in the presence of effects.

For example, consider the dequeue operation in the previous example reproduced below:

```python
...
let dequeue () =
    if Queue.is_empty run_q then () (* done *)
    else (Queue.pop run_q) ()
```

If the scheduler queue is empty, dequeue considers that the scheduler is done and returns to the caller. However, there may still be a task waiting to exchange a value (stored in the reference cell `exchanger`), which remains blocked forever! If the blocked task holds onto resources, these resources are leaked. For example, consider the following task:

```python
let leaky_task () =
    fork (fun _ ->
        let oc = open_out "secret.txt" in
        Fun.protect ~finally: (fun _ -> close_out oc) (fun _ ->
            output_value oc (xchg 0)))
```

The task writes the received message to the file `secret.txt`. It uses `Fun.protect` to ensure that the output channel `oc` is closed on both normal and exceptional return cases. Unfortunately, this is not sufficient. If the exchange effect `xchg 0` cannot be matched with an exchange effect performed by some other thread, then this task remains blocked forever. Thus, the output channel `oc` is never closed.

To avoid this problem, one must adhere to a simple discipline: *every continuation must be eventually either continued or discontinued*. Here, we use `discontinue` to ensure that the blocked task does not remain blocked forever. By discontinuing this task, we force it to terminate (with an exception):
## 12.24.10 Unhandled effects

Unlike languages such as Eff and Koka, effect handlers in OCaml do not provide *effect safety*; the compiler does not statically ensure that all the effects performed by the program are handled. If effects do not have a matching handler, then an `Effect.Unhandled` exception is raised at the point of the corresponding `perform`. For example, in the previous example, `bar` does not handle the effect `F`. Hence, we will get an `Effect.Unhandled F` exception when we run `bar`.

```ocaml
try bar () with Effect.Unhandled F -> "Saw Effect.Unhandled exception"
```

```
- : string = "Saw Effect.Unhandled exception"
```

## 12.24.11 Linear continuations

As discussed earlier 12.24.4, the delimited continuations in OCaml must be used linearly – *every captured continuation must be resumed either with a continue or discontinue exactly once*. Attempting to use a continuation more than once raises a `Continuation_already_resumed` exception. For example:

```hl
try_with perform (Xchg 0)
  { effc = fun (type a) (eff : a t) ->
    match eff with
    | Xchg n -> Some (fun (k: (a, _ ) continuation) ->
                        continue k 21 + continue k 21)
    | _ -> None }
```

Exception: Stdlib.Effect.Continuation_already_resumed.

The primary motivation for adding effect handlers to OCaml is to enable concurrent programming. One-shot continuations are sufficient for almost all concurrent programming needs. They are also much cheaper to implement compared to multi-shot continuations since they do not require stack frames to be copied. Moreover, OCaml programs may also manipulate linear resources such as sockets and file descriptors. The linearity discipline is easily broken if the continuations are allowed to resume more than once. It would be quite hard to debug such linearity violations on resources due to the lack of static checks for linearity and the non-local nature of control flow. Hence, OCaml does not support multi-shot continuations.

While the “at most once resumption” property of continuations is ensured with a dynamic check, there is no check to ensure that the continuations are resumed “at least once”. It is left to the user to ensure that the captured continuations are resumed at least once. Not resuming continuations will leak the memory allocated for the fibers as well as any resources that the suspended computation may hold.

One may install a finaliser on the captured continuation to ensure that the resources are freed:

```hl
exception Unwind
Gc.finalise (fun k ->
  try ignore (discontinue k Unwind) with _ ->()) k
```

In this case, if `k` becomes unreachable, then the finaliser ensures that the continuation stack is unwound by discontinuing with an `Unwind` exception, allowing the computation to free up resources. However, the runtime cost of finalisers is much more than the cost of capturing a continuation.
exception Improper_synchronization

let dequeue () =
    if Queue.is_empty run_q then begin
        match !exchanger with
        | None -> () (* done *)
        | Some (n, k) ->
           exchanger := None;
           discontinue k Improper_synchronization
    end else (Queue.pop run_q) ()

When the scheduler queue is empty and there is a blocked exchanger thread, the dequeue function discontinues the blocked thread with an Improper_synchronization exception. This exception is raised at the blocked xchg function call, which causes the finally block to be run and closes the output channel oc. From the point of view of the user, it seems as though the function call xchg 0 raises the exception Improper_synchronization.

### 12.24.5 Control inversion

When it comes to performing traversals on a data structure, there are two fundamental ways depending on whether the producer or the consumer has the control over the traversal. For example, in List.iter f 1, the producer List.iter has the control and pushes the element to the consumer f who processes them. On the other hand, the Seq[29.53] module provides a mechanism similar to delayed lists where the consumer controls the traversal. For example, Seq.forever Randombool returns an infinite sequence of random bits where every bit is produced (on demand) when queried by the consumer.

Naturally, producers such as List.iter are easier to write in the former style. The latter style is ergonomically better for the consumer since it is preferable and more natural to be in control. To have the best of both worlds, we would like to write a producer in the former style and automatically convert it to the latter style. The conversion can be written *once and for all* as a library function, thanks to effect handlers. Let us name this function invert. We will first look at how to use the invert function before looking at its implementation details. The type of this function is given below:

val invert : iter:(( 'a -> unit) -> unit) -> 'a Seq.t

The invert function takes an iter function (a producer that pushes elements to the consumer) and returns a sequence (where the consumer has the control). For example,

let lst_iter = Fun flip List.iter [1;2;3]
val lst_iter : (int -> unit) -> unit = <fun>

is an iter function with type (int -> unit) -> unit. The expression lst_iter f pushes the elements 1, 2 and 3 to the consumer f. For example,

lst_iter (fun i ->FORMATf.printf "%d
" i)
1
2
3
- : unit = ()
Hence, it is recommended that the user take care of resuming the continuation exactly once rather than relying on the finaliser.

### 12.24.12 Shallow handlers

The examples that we have seen so far have used *deep* handlers. A deep handler handles all the effects performed (in sequence) by the computation. Whenever a continuation is captured in a deep handler, the captured continuation also includes the handler. This means that, when the continuation is resumed, the effect handler is automatically re-installed, and will handle the effect(s) that the computation may perform in the future.

OCaml also provides *shallow* handlers. Compared to deep handlers, a shallow handler handles only the first effect performed by the computation. The continuation captured in a shallow handler does not include the handler. This means that, when the continuation is resumed, the handler is no longer present. For this reason, when the continuation is resumed, the user is expected to provide a new effect handler (possibly a different one) to handle the next effect that the computation may perform.

Shallow handlers make it easier to express certain kinds of programs. Let us implement a shallow handler that enforces a particular sequence of effects (a protocol) on a computation. For this example, let us consider that the computation may perform the following effects:

```hml
type _ Effect.t += Send : int -> unit Effect.t
| Recv : int Effect.t
```

Let us assume that we want to enforce a protocol that only permits an alternating sequence of `Send` and `Recv` effects that conform to the regular expression `(Send;Recv)*;Send?`. Hence, the sequence of effects `[]` (the empty sequence), `[Send]`, `[Send;Recv]`, `[Send;Recv;Send]`, etc., are allowed, but not `[Recv]`, `[Send;Send]`, `[Send;Recv;Recv]`, etc. The key observation here is that the set of effects handled evolves over time. We can enforce this protocol quite naturally using shallow handlers as shown below:

```hml
open Effect.Shallow

let run (comp: unit -> unit) : unit =
let rec loop_send : type a. (a,unit) continuation -> a -> unit = fun k v ->
continue_with k v
{ retc = Fun.id;
  exnc = raise;
  effc = fun (type b) (eff : b Effect.t) ->
    match eff with
    | Send n -> Some (fun (k: (b,_) continuation) ->
                        loop_recv n k())
    | Recv -> failwith "protocol violation"
    | _ -> None }
and loop_recv : type a. int -> (a,unit) continuation -> a -> unit = fun n k v ->
continue_with k v
{ retc = Fun.id;
  exnc = raise;
  effc = fun (type b) (eff : b Effect.t) ->
```