Hello Here is the latest OCaml Weekly News, for the week of January 07 to 14, 2025. Table of Contents ───────────────── On concurrency models OCaml 5.3.0 released dream-html and pure-html 3.9.5 Building an OCaml cross compiler with OCaml 5.3 Ppx deriving decoders Ortac 0.5.0 testing higher order functions Other OCaml News Old CWN On concurrency models ═════════════════════ Archive: Deep in this thread, Calascibetta Romain announced ────────────────────────────────────────────────── For those interested, we've spent some time writing [a book] on how to use Miou and asynchronous programming with Miou — basically, it introduces Miou's design. In addition, resources that may be of interest are: • [a retrospective] of a handheld scheduler implementation compared to what Miou offers • [a manifesto] that says the same thing as what I said above A next release of Miou is in preparation and additions to this ‘little book’ will be made. In particular, there will be an explanation of how we implemented [happy-eyeballs], which remains a good example. [a book] [a retrospective] [a manifesto] [happy-eyeballs] OCaml 5.3.0 released ════════════════════ Archive: octachron announced ─────────────────── We have the pleasure of announcing the release of OCaml version 5.3.0. dedicated to the memory of John William Mauchly and Paul Verlaine on the anniversary of their death. De la musique avant toute chose, Et pour cela préfère l’Impair (Music first and foremost of all! Choose your measure of odd not even) Some of the highlights in OCaml 5.3.0 are: • Syntax for deep effect handlers There is now a dedicated syntax for installing deep effect handler ┌──── │ match f () with │ | x -> x │ | effect Random_float, k -> Effect.Deep.continue k (Random.float 1.0) └──── This new syntax adds a new `effect' keyword, which may break existing code. To improve backward compatibility, this new keyword can be disabled with the new `-keywords' flags if needed for backward compatibility. • Restored MSVC port It is now possible to use the MSVC toolchain on Windows, restoring the last missing port from OCaml 4 (except for the native compiler support for 32-bit architectures which is not planned) • Re-introduced statistical memory profiling (statmemprof) The submodule `Gc.memprof' is restored with a slightly different API. This submodule can be used to monitor memory allocation statistics inside a program. In OCaml 5, each domain can be monitored independently while child domains inherit the parent domain profiling profile (if there is one active). • utf-8 encoded Unicode source files and modest support of Unicode identifiers ┌──── │ type saison = Hiver | Été | Printemps | Automne └──── The OCaml lexer has been extended to support a modest subset of Unicode characters in identifiers. This is mostly intended for pedagogical use. This extended support requires source files to be utf-8 encoded Unicode text. • More space-efficient implementation of Dynarray The internal implementation of `Dynarray' now uses an unboxed representation which avoids the need of storing items wrapped in a `Some x' block and thus save some spaces and indirections. • Improved metadata on the pairs of declarations and definitions for merlin. The metadata stored inside cmt files has been improved to better distinguish the provenance of identifiers (previous versions could confuse an interface and implementation identifier). Similarly, the metadata now tracks more precisely the association between declarations and definitions. For instance, in ┌──── │ module X = struct let x = 0 end │ module M: sig │ val x: int │ end = struct │ let x = 1 │ include X │ end └──── Merlin can now determine that the definition of the `M.x' value lies inside the module `X'. And a lot of incremental changes: • Around 20 new functions in the standard library (in the `Domain', `Dynarray', `Format', `List', `Queue', `Sys', and `Uchar' modules). • Many fixes and improvements in the runtime • Improved error messages for first-class modules, functors, labelled arguments, and type clashes. • Numerous bug fixes Please report any unexpected behaviours on the [OCaml issue tracker]. The full list of changes can be found in the changelog below. /editor note: please visit for the changelog/ Happy hacking, Florian Angeletti for the OCaml team. [OCaml issue tracker] dream-html and pure-html 3.9.5 ══════════════════════════════ Archive: Yawar Amin announced ──────────────────── Happy to announce that dream-html and pure-html 3.9.5 are now available on opam. This is a significant release with three main new things: 1. Type-safe paths and routing 2. Support for static asset caching 3. HTML improvements Type-safe paths and routing ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ Allows defining paths as values that can be handled by a router and _also_ rendered by the HTML markup generator, so that the actual routed paths are in sync with the rendered paths in the application. These paths use OCaml's built-in format strings rather than a new DSL: eg `/orders/%s/versions/%d'. This makes it possible to extract type-safe values from path segments and pass them to the handler; render markup with guaranteed correct paths; and refactor the app's paths without having to hunt for hard-coded strings. See [the docs] for details. [the docs] Static assets support ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ Automates the handling of static assets in the application so that they can easily be served by the router with an immutable cache policy and their paths can be rendered in markup with a content-based revision hash, for easy cache-busting. Added a new CLI tool `dreamwork' which helps with scaffolding this static assets setup. The intention is to use it for more scaffolding tasks in the future–stay tuned. See [the docs] for details, and [this screen recording] for a short demo. [the docs] [this screen recording] HTML improvements ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ Thanks to [RezwanArefin01] for prettifying the generated HTML. It is now formatted and much easier to read. See the [snapshots] for some examples. Lastly, added `HTML.as_' which is the [as attribute]. Enjoy! [RezwanArefin01] [snapshots] [as attribute] Building an OCaml cross compiler with OCaml 5.3 ═══════════════════════════════════════════════ Archive: shym announced ────────────── A cross compiler is a compiler that runs on some _host_ machine, for instance one running Linux on a 64-bit ARM processor, and generates code for a different _target_ machine, for instance one running Windows with a 64-bit x86 processor. Building OCaml cross compilers used to be quite tricky and hackish but many incremental changes to the build system over the last years have improved radically the situation. So much so that, with the most recent changes ([1], [2]) in the development branch of the compiler, it should be possible to build many cross compilers without extra changes :crossed_fingers: This is all well and good, you might say, but you would rather play with the brand new [5.3] instead of a development branch! So I’ve backported the necessary changes to 5.3. [1] [2] [5.3] How to build and use a OCaml 5.3 cross compiler ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ To make it easy to test, I’ve written an example OPAM file that can be customised to suit your goal. It takes the example of building a cross compiler to 64-bit x86 Windows MinGW, in particular because that always reveals unexpected issues :-) 1. Start by creating a 5.3.0 OPAM switch if you haven’t already. 2. Choose the target you want to create a cross compiler for and find its [target triplet]. The GCC C cross compilers and the GNU cross binutils use target triplets as prefixes for the commands, so an easy way to find your triplet is to install the tools. So: 3. Install the C cross compiler and toolchain for your target. Many Linux distributions package some cross compilers. For instance, the [CI tests for cross compilers] installs on Ubuntu: • the `gcc-mingw-w64-x86-64' package (which depends on the matching binutils) to cross compile to 64-bit x86 Windows MinGW; in that case, that target machine is identified by the `x86_64-w64-mingw32' triplet, so it calls `configure' with the argument `--target=x86_64-w64-mingw32', • the `gcc-aarch64-linux-gnu' package to cross compile to 64-bit arm Linux; in that case, the target machine is identified by the `aarch64-linux-gnu' triplet. 4. Create a new OPAM package interactively for instance by choosing the name of the package (`ocaml-xyz' or even `ocaml-cross-xyz' are good choices I’d say; my [example] uses `ocaml-cross-windows', for instance) and run: ┌──── │ opam pin add --edit ocaml-cross-xyz - └──── This will open an editor so that you can fill in the instructions on how to build your cross compiler. Use my [example] to get you started. In particular you’ll want to configure the `--target' parameter with the triplet for your target (that could be the only change!). If your toolchain and C compiler use that triplet as a prefix for all the commands, `configure' will find them automatically. Otherwise you’ll need to explicitly set them, by adding arguments such as `CC=...' to `configure'. The [CI tests for cross compilers] contains such an example to cross compile to Android where `CC', `AR', `PARTIALLD', `RANLIB' and `STRIP' are explicitly set… In other words, I suggest to experiment first with an example with automatic configuration! You should now have a cross compiler! Let’s use it on a simple sanity check `test.ml': ┌──── │ (* Is the proper (target) OS identified? *) │ let _ = │ Printf.printf "Version: %s\nOS: %s\nUnix: %b\nWin: %b\nCygwin: %b\n" │ Sys.ocaml_version Sys.os_type Sys.unix Sys.win32 Sys.cygwin │ │ (* Do the compiler libs work? *) │ (* The interface for [Arch] is not the same across processor architectures, the │ following assumes your target is 64-bit x86 *) │ let _ = │ Printf.printf "allow_unaligned_access = %b\n" Arch.allow_unaligned_access; │ Printf.printf "win64 = %b\n" Arch.win64 └──── The package `ocaml-cross-xyz' will install an `ocamlfind' toolchain called `xyz'. So we can compile `test.ml' thus: ┌──── │ ocamlfind -toolchain xyz opt -package compiler-libs.optcomp -linkpkg test.ml -verbose └──── where `-verbose' let you check what is actually being run. If your target is Windows MinGW (so cross compiling from some unix), you probably need an extra step before this compilation can go through: the tool `flexlink.exe' which is used to link the final Windows binary has been built as part of the package but `ocamlopt' will expect to find a command `flexlink' (note in particular the absence of `.exe') so I suggest to `ln -s' the `flexlink' binary somewhere in your `PATH'. For instance, it could be: ┌──── │ ln -s "$(opam show --list-files ocaml-cross-xyz | grep flexlink.opt.exe)" ~/bin/flexlink └──── and then you will be able to run the `ocamlfind -toolchain ...' command to compile your program. [target triplet] [CI tests for cross compilers] [example] Gotchas and details ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 1. Beware that having a `flexlink' command in `PATH' breaks OCaml (5.3 and before)’s `configure' if you’re not on Windows; this will be fixed in 5.4. 2. The [example] OPAM package contains SHA256 sums for `.patch' files generated on the fly from the corresponding commits but they might change without notice (to add an extra digit to the SHA1 they contain, for instance). If you notice that, ping me so that I can update the SHA256 sums in the gist. 3. The [example] OPAM package pulls the official OCaml 5.3.0 archive along with two patches: • the first one is a large commit that squashes all the commits that I backported from upstream, • the second one is a small commit that adds the generation of the `ocamlfind' toolchain configuration. You can find the detailed backport on my [`5.3+ocross'] branch and its [comparison] with the official release. The squashed commit lives on its [own branch]. [example] [`5.3+ocross'] [comparison] [own branch] Ppx deriving decoders ═════════════════════ Archive: Ben Bellick announced ───────────────────── A little late but wanted to share a package I have released! For those familiar with the excellent [ocaml-decoders] package, I have written [ppx_deriving_decoders] to automatically generate the corresponding decoders (and encoders) based off of type definitions. In my view, this gives the best of both worlds in terms of: 1. automatically generating (e.g. JSON) serialization and deserialization based off of a type definition, and 2. having a readable and expressive language for handwriting encoders and decoders when necessary by using combinators. The instructions in the README demonstrate how you can use the generated decoder as a base point from which to hand tweak and get your own custom decoder. Please let me know if you find it useful or have any feedback. Thanks! [ocaml-decoders] [ppx_deriving_decoders] Ortac 0.5.0 testing higher order functions ══════════════════════════════════════════ Archive: Nicolas Osborne announced ───────────────────────── Hi everyone! I'm very pleased to announce the release of the Ortac-0.5.0 packages for specification-driven testing! Ortac/QCheck-STM is a test generator based on the [QCheck-STM] model-based testing framework and the [Gospel] specification language for OCaml. This new release brings three new features. In the effort to increase the coverage of the generated tests and thanks to Jan Midtgaard, we now support testing higher order functions. Thanks Jan! It is also now possible to test a module exposed as a sub-module by Dune, specifying the module's prefix in a CLI optional argument. A feature that we've been asked to add. And to test an actual sub-module defined inside an OCaml file, specifying the sub-module in a CLI optional argument as well. Ortac/Dune generates the Dune boilerplate for you. It has been updated to support the two new optional arguments. You can install those packages via opam: ┌──── │ $ opam install ortac-qcheck-stm ortac-dune └──── Then you write some Gospel specifications in your library's interface file `foo.mli': ┌──── │ type 'a t │ (*@ mutable model contents : 'a sequence *) │ │ val make : int -> 'a -> 'a t │ (*@ t = make i a │ ensures t.contents = Sequence.init i (fun _ -> a) *) │ │ val for_all : ('a -> bool) -> 'a t -> bool │ (*@ b = for_all p t │ ensures b = Sequence.fold_left (fun acc a -> acc && p a) true t.contents *) └──── Then a simple configuration file `foo_config.ml': ┌──── │ type sut = char t │ │ let init_sut = make 42 'a' └──── And you can generate some specification-driven model-based tests for your library just by running: ┌──── │ $ ortac qcheck-stm foo.mli foo_config.ml └──── If you want to integrate the generation and the running of the tests to your dune setup (which is highly recommended), just add the following stanza to your dune file in your test directory: ┌──── │ (rule │ (alias runtest) │ (mode promote) │ (action │ (with-stdout-to │ dune.inc │ (run ortac dune qcheck-stm foo.mli)))) │ │ (include dune.inc) └──── You'll find more information in the [Ortac/QCheck-STM documentation], the [Ortac/Dune README] and the [`examples' folder]. I'm also happy to answer questions. Happy testing! [QCheck-STM] [Gospel] [Ortac/QCheck-STM documentation] [Ortac/Dune README] [`examples' folder] Other OCaml News ════════════════ From the ocaml.org blog ─────────────────────── Here are links from many OCaml blogs aggregated at [the ocaml.org blog]. • [The Most Elegant Configuration Language] [the ocaml.org blog] [The Most Elegant Configuration Language] Old CWN ═══════ If you happen to miss a CWN, you can [send me a message] and I'll mail it to you, or go take a look at [the archive] or the [RSS feed of the archives]. If you also wish to receive it every week by mail, you may subscribe to the [caml-list]. [Alan Schmitt] [send me a message] [the archive] [RSS feed of the archives] [caml-list] [Alan Schmitt]