OCaml Weekly News
Hello
Here is the latest OCaml Weekly News, for the week of January 07 to 14, 2025.
Table of Contents
On concurrency models
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.
OCaml 5.3.0 released
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 aSome 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 moduleX
.
And a lot of incremental changes:
- Around 20 new functions in the standard library (in the
Domain
,Dynarray
,Format
,List
,Queue
,Sys
, andUchar
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 https://discuss.ocaml.org/t/ocaml-5-3-0-released/15916 for the changelog
Happy hacking, Florian Angeletti for the OCaml team.
dream-html and pure-html 3.9.5
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:
- Type-safe paths and routing
- Support for static asset caching
- 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.
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.
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!
Building an OCaml cross compiler with OCaml 5.3
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.
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 :-)
- Start by creating a 5.3.0 OPAM switch if you haven’t already.
- 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:
- 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 thex86_64-w64-mingw32
triplet, so it callsconfigure
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 theaarch64-linux-gnu
triplet.
- the
Create a new OPAM package interactively for instance by choosing the name of the package (
ocaml-xyz
or evenocaml-cross-xyz
are good choices I’d say; my example usesocaml-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 asCC=...
toconfigure
. The CI tests for cross compilers contains such an example to cross compile to Android whereCC
,AR
,PARTIALLD
,RANLIB
andSTRIP
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.
Gotchas and details
- Beware that having a
flexlink
command inPATH
breaks OCaml (5.3 and before)’sconfigure
if you’re not on Windows; this will be fixed in 5.4. - 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. 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.
Ppx deriving decoders
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:
- automatically generating (e.g. JSON) serialization and deserialization based off of a type definition, and
- 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!
Ortac 0.5.0 testing higher order functions
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!
Other OCaml News
From the ocaml.org blog
Here are links from many OCaml blogs aggregated at the ocaml.org blog.
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.