OCaml 5.5.0

cod1r1 pts0 comments

OCaml 5.5.0 released - Ecosystem - OCaml

= 40rem)" rel="stylesheet" data-target="desktop" />

= 40rem)" rel="stylesheet" data-target="chat_desktop" /><br>= 40rem)" rel="stylesheet" data-target="discourse-ai_desktop" /><br>= 40rem)" rel="stylesheet" data-target="discourse-calendar_desktop" /><br>= 40rem)" rel="stylesheet" data-target="poll_desktop" />

OCaml 5.5.0 released

Ecosystem

compiler,<br>announce

octachron

June 19, 2026, 9:35pm

We have the pleasure of celebrating the birthday of Blaise Pascal by announcing the release of OCaml version 5.5.0.

Some of the highlights in OCaml 5.5.0 are:

Module-dependent Functions

Modules can now be used as function arguments in a form of lightweight functors.

For instance, we can define a function for printing a map generated by

the Map.Make functor:

let pp_map (module M: Map.S) pp_key pp_v ppf set =<br>if M.is_empty set then<br>Format.fprintf ppf "ø"<br>else<br>let pp_sep ppf () = Format.fprintf ppf ",@ " in<br>let pp_binding ppf (k,v) =<br>Format.fprintf ppf "@[%a@ =@ %a@]" pp_key k pp_v v<br>in<br>Format.fprintf ppf "@[{@ %a@ }@]"<br>(Format.pp_print_seq ~pp_sep pp_binding) (M.to_seq set)

We can then apply this function on a string map

module String_map = Map.Make(String)

with

let () =<br>let m = String_map.of_list ["Zero", "Zero"; "One", "Un"] in<br>let pp_str = Format.pp_print_string in<br>Format.printf "%a@."<br>(pp_map (module String_map) pp_str pp_str) m

Compared to first-class modules, the type of the function pp_map

type 'a printer = Format.formatter -> 'a -> unit<br>val pp_map: (module M: Map.S) -> M.key printer -> 'a printer -> 'a M.t printer

is dependent over the value of the module S, and thus the function can only

applied over a statically known module:

let f (): (module Map.S) =<br>if Random.bool () then<br>(module Map.Make(Int))<br>else<br>(module Map.Make(Float))<br>let fail = pp_map (f ())

Error: This expression has type<br>(module M : Map.S) -><br>(Format.formatter -> M.key -> unit) -><br>(Format.formatter -> 'a -> unit) -> Format.formatter -> 'a M.t -> unit<br>but an expression was expected of type (module Map.S) -> 'b<br>The module M would escape its scope<br>This function is module-dependent. The dependency is preserved<br>when the function is passed a static module argument (module M : S)<br>or (module M). Its argument here is not static, so the type-checker<br>tried instead to change the function type to be non-dependent.

Relocatable Compiler

A compiler installation can now be moved or copied with no risk

of hard-to-debug errors due to mixing incompatible bytecode runtime interpreters.

In practice, this means that creating a local switch when there is a

global switch with the same compiler version and configuration

available can be done by cloning the global switch rather than

recompiling the whole compiler.

This should considerably reduce the time required to create

new local opam switches out-of-the-box.

Polymorphic Functions as Function Arguments

Higher-rank polymorphic functions can now be defined directly by

using an explicit type annotation in a function argument

let apply_map (map: 'a 'b. ('a -> 'b) -> 'a list -> 'b list) =<br>map string_of_int [1;2;3], map List.singleton ["x"; "y"]<br>let _ = apply_map List.map

Previously defining such a function required going through either a record or an object

with a polymorphic field or methods

type map = { map: 'a 'b. ('a -> 'b) -> 'a list -> 'b list }<br>let apply_map {map} =<br>map string_of_int [1;2;3], map List.singleton ["x"; "y"]

Search and Replace Substring Functions

The String module has been extended with many functions

for searching and replacing substrings inside a string.

let _true = String.includes ~affix:"aba" "abbaba"<br>let sentence = String.replace_all ~sub:"𝄽" ~by:"word" "A 𝄽 is re𝄽ed"

The substring search is using the 2-way string matching algorithm

which has the advantage of requiring constant space memory overhead

independently of the needle size.

Generalised Local Definitions

It is now always possible to define locally a type,

a class, a module type or any kind of item that can be defined

globally:

let mandelbrot n x =<br>let type t = Converge | Escape of int in<br>...<br>match orbit n x with<br>| Converge -> 0<br>| Exit_at n -> colorize n

External Types

When interfacing with foreign function libraries, it is now possible

to define external type

type int_gmp = external "mpz_t"<br>type float_gmp = external "mpf_t"

Compared to an abstract type definition, the external type name

“mpz_t” (resp. mpf_t) makes the type distinguishable from any

non-abstract types or external types with a different name.

In particular, this makes FFI types better behaved when combined with

Generalised Abstract Data Types (GADTs). For instance, The typechecker

is able to prove that

let ok: (int_gmp,[` A] ) Type.eq -> _ = function _ -> .

is a total function because the external type int_gmp is not compatible

with a polymorphic variant type.

Warning: Abstract types in the current module

The astute reader has probably noticed in the definition above that,

in...

module type function format string list

Related Articles