Attn: Development Editor, Latest OCaml Weekly News
Alan Schmitt <[email protected]> Tue, 21 Apr 2026 11:34:20 +0200
| Newsgroups | gmane.comp.lang.caml.inria |
|---|---|
| Message-ID | <[email protected]> |
--===-=-=
Content-Type: multipart/mixed; boundary="=-=-="
--=-=-=
Content-Type: multipart/alternative; boundary="==-=-="
--==-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Hello
Here is the latest OCaml Weekly News, for the week of April 14 to 21,
2026.
Table of Contents
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80
http-date v0.2 =E2=80=94 Zero-dependency HTTP date parsing for OCaml
Caqti 2.3.0
layoutz 0.1.0 =F0=9F=AA=B6 - Zero-dep Elm-style TUIs and terminal plots for=
your OCaml apps
Dune 3.22
ptt, a mailing list system as unikernel
Mollymawk and Albatross orchestrating all virtual machines
OUPS meetup april 2026
Stk 0.6 released
opam 2.5.1
Restarting OCaml.jp: The OCaml Japan User Group
Code navigation and search on Github
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries
ppx_mixins: slightly more elegant mixin syntax
Experience Report: Refining Dune=E2=80=99s Dependency Graph
First beta release of OCaml 5.5.0
ocgtk 0.1: OCaml bindings for GTK 4 (preview release)
Old CWN
http-date v0.2 =E2=80=94 Zero-dependency HTTP date parsing for OCaml
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-http-date-v0-2-zero-dependency-http-date=
-parsing-for-ocaml/17984/1>
Bikal Lem announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80
I just released v0.2 of http-date, an RFC 9110 compliant HTTP datetime
decoder/encoder for OCaml.
This is a major rewrite from v0.1. Here's what changed:
Zero dependencies =E2=80=94 Replaced the ocamllex/menhir parser with a
hand-written implementation and removed the ptime dependency
entirely. The library now only requires ocaml and dune.
New type-safe API =E2=80=94 The parsed result is now a polymorphic variant
tagged by format (IMF, RFC850, `ASCTIME), so you always know which
HTTP date format was parsed. The dayname, date, time, and datetime
types are all exposed in the public API.
Serious testing =E2=80=94 Added property-based tests with alcobar and AFL=
fuzz
testing infrastructure to build confidence in the hand-written parser.
If you're working with HTTP headers in OCaml, give it a try:
opam install http-date
<https://github.com/bikallem/http-date>
Caqti 2.3.0
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90
Archive: <https://discuss.ocaml.org/t/ann-caqti-2-3-0/17985/1>
Petter A. Urkedal announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80
I would like to announce the release of [Caqti] 2.3.0.
TL;DR: Consider adding the `caqti.classic' to your link line
(available since this version). It currently only re-exports the
`caqti' library, but will be replaced by a compatibility layer for the
Caqti 2 API in Caqti 3 to allow incremental migration.
[Caqti] <https://github.com/paurkedal/ocaml-caqti>
Release Notes
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
Note that some of the new features of this release are only accessible
through the still unstable `caqti.template' library, which will soon
be stabilized as part of an upcoming Caqti 3 API. Due to adjustments
to module names, switching to `caqti.template' will not ensure future
compatibility. Instead, users are encouraged to add the new
`caqti.classic' to their dependencies to ease migration to Caqti 3.
=E2=80=A2 Added an alias `caqti.classic' for the `caqti' library. This w=
ill
be turned into a library providing compatibility with the current
Caqti 2 API when Caqti 3 is released. The two APIs can be used
side-by-side to allow incremental migration.
=E2=80=A2 The dialect descriptor for MariaDB in `caqti.template' now prov=
ides
the server version.
=E2=80=A2 Added `Query.parens', `Query.litf', `Query.vars', `Row_type.fie=
lds'
to the `caqti.template' library.
=E2=80=A2 Revised the interface for creating row types to allow instantia=
ting
parametric types applicatively. Before this change, each
application of a function representing a parametric type would
generate a new type ID even when applied to the same type parameter
argument. The key part of this interface is the
`Caqti_template.Constructor_type' module.
=E2=80=A2 The query functions provided to request templates are now memoi=
zed,
so that they are only called once per dialect. This is meant as an
optimization; it's still good practise to avoid side-effects here.
=E2=80=A2 The new function `Query.with_pos_of' allows query generators to=
add
source locations to the syntax tree, which will be emitted as SQL
comments in the query string if the `enable_query_annotations' is
set. This should simplify debugging when the query is assembled
from different parts of the application code.
=E2=80=A2 The still unstable `caqti.template' library now supports multip=
le
statements in a single request template, sent opportunistically as a
single query where allowed. This is still experimental.
=E2=80=A2 Fixed package scoping of shim rules for sqlite3 (#133 by mefyl).
=E2=80=A2 Fixed the error classification for the SQLite3 driver (#132).
=E2=80=A2 Fixed reconnect after connection loss for PostgreSQL.
layoutz 0.1.0 =F0=9F=AA=B6 - Zero-dep Elm-style TUIs and terminal plots for=
your OCaml apps
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-layoutz-0-1-0-zero-dep-elm-style-tuis-te=
rminal-plots-for-your-ocaml-apps/17986/1>
Matthieu Court announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Hello all! Thanks for your feedback last time - [layoutz] now has an
Elm-style TUI runtime (quite [different in spirit] than (the
excellent) Minttea) =E2=80=A6 a smoothed API .. and terminal plot built-i=
ns.
Looking for feedback! Many thanks
[layoutz]
<https://github.com/mattlianje/layoutz/tree/master/layoutz-ocaml>
[different in spirit]
<https://github.com/mattlianje/layoutz/tree/master/layoutz-ocaml#faq>
Dune 3.22
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90
Archive: <https://discuss.ocaml.org/t/ann-dune-3-22/17912/3>
Continuing this thread, Shon announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
The Dune team is pleased to announce [the release of dune 3.22.2].
This is a patch release consisting of bug fixes. See [the full
changelog] for all the changes and for attribution to the contributors
who made it all possible. Thank you, contributors!
If you encounter a problem with this release, please report it in [our
issue
[the release of dune 3.22.2]
<https://github.com/ocaml/dune/releases/tag/3.22.2>
[the full changelog] <https://github.com/ocaml/dune/releases/tag/3.22.2>
Fixed
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
=E2=80=A2 Revert the change in behavior of `--diff-command' back to
3.21. Non-existent files are now passed to this command instead of
being replaced with /dev/null ([#14098], fixes 13891, [@rgrinberg])
[#14098] <https://github.com/ocaml/dune/pull/14098>
[@rgrinberg] <https://github.com/rgrinberg>
ptt, a mailing list system as unikernel
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-ptt-a-mailing-list-system-as-unikernel/1=
7987/1>
Calascibetta Romain announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Hey! We just launched a new mailing list powered entirely by OCaml
unikernels. The website (itself a unikernel) is at
<https://mailingl.st>. You can subscribe to [email protected] by sending
an email to [email protected] if you're interested in the
development and deployment of SMTP-related unikernels.
Fair warning: this is still a *public test* mailing list for now. In
the long run, it will focus on our ptt project.
The SMTP protocol: a long and winding road!
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C
=E2=97=8A In the beginning, email
It all started with [Mr.MIME], our library for decoding and encoding
emails. It's a synthesis of the relevant RFCs, but more importantly
it's been battle-tested against real-world emails from the IEEE,
[Enron], [KVM] and, most recently, the [caml-list].
This work also let us build [Hamlet], a database of valid random
emails generated using a fuzzer.
Under the hood, Mr.MIME relies on [unstrctrd] for decoding the most
general form of values found in an email (with internationalisation
support via [rosetta]) and [prettym] for encoding emails while
respecting SMTP constraints and (Comment) Folding Whitespace handling.
[Mr.MIME] <https://github.com/mirage/mrmime>
[Enron] <https://www.cs.cmu.edu/~enron/>
[KVM] <https://yhbt.net/lore/kvm/>
[caml-list]
<https://discuss.ocaml.org/t/is-there-a-public-archive-for-the-caml-list/=
16374/6?u=3Ddinosaure>
[Hamlet] <https://github.com/mirage/hamlet>
[unstrctrd] <https://github.com/dinosaure/unstrctrd>
[rosetta] <https://github.com/mirage/rosetta>
[prettym] <https://github.com/dinosaure/prettym>
=E2=97=8A Next, the protocol
Then came [colombe], our OCaml implementation of the SMTP protocol. It
uses [ocaml-tls] for `STARTTLS' support.
The protocol is supposedly "simple" (though the Internet always has
surprises in store), but from day one we designed colombe to be
independent of any scheduler and network layer. That way it slots
right into unikernels without friction.
[colombe] <https://github.com/mirage/colombe>
[ocaml-tls] <https://github.com/mirleft/ocaml-tls>
=E2=97=8A Finally, legitimacy
On top of these core components, we built several email security
layers:
=E2=80=A2 [ocaml-dkim] handles signing and verifying email integrity in a
streaming fashion (both for verification and signature generation)
=E2=80=A2 [uspf] verifies sender identity and, like most of our libraries,
stays independent of any scheduler or DNS implementation
=E2=80=A2 [ocaml-dmarc] automates DKIM and SPF verification, stamps emails
with the result, and checks alignment across a domain name
=E2=80=A2 [ocaml-arc](github.com/robur-coop/ocaml-arc) lets you verify and
sign emails to complete a chain of trust when an email passes
through multiple SMTP servers (which is exactly what happens with a
mailing list)
We wrote a short article about all of this [here].
[ocaml-dkim] <https://github.com/mirage/ocaml-dkim>
[uspf] <https://github.com/mirage/uspf>
[ocaml-dmarc] <https://github.com/dinosaure/ocaml-dmarc>
[here]
<https://blog.robur.coop/articles/2025-04-23-email-verification.html>
All in the form of unikernels
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
Our first experiments already showed that we [could handle emails]
with MirageOS unikernels. But we also hit real limitations: memory
leaks, security vulnerabilities, and build issues.
So we decided to start fresh, and take the opportunity to fully
embrace OCaml 5 and effects. We rebuilt the key pieces from scratch:
=E2=80=A2 a new effect-based scheduler: [Miou]/[Mkernel]
=E2=80=A2 a much more complete TCP/IP stack: [Mnet]
=E2=80=A2 a new FAT32 file system: [Mfat]
`ptt' is built on this new stack, and so far we haven=E2=80=99t observed =
any
memory leaks (thanks to [mkernel-memtrace] for tracing memory usage,
viewable via [memtrace-viewer]). The CVEs related to [mirage-tcpip]
were taken into account during ~mnet~=E2=80=99s development, and the build
story is much simpler now. A GitHub action can build and actually run
the unikernel to test it, as you can see with [mnet].
Other unikernels using this approach are available too. If you=E2=80=99re
curious, check out [this tutorial] on creating a unikernel in OCaml.
[could handle emails] <https://mirage.io/blog/2022-04-01-Mr-MIME>
[Miou] <https://github.com/robur-coop/miou>
[Mkernel] <https://github.com/robur-coop/mkernel>
[Mnet] <https://github.com/robur-coop/mnet>
[Mfat] <https://github.com/robur-coop/mfat>
[mkernel-memtrace] <https://git.robur.coop/robur/miou-solo5-memtrace>
[memtrace-viewer] <https://github.com/janestreet/memtrace/>
[mirage-tcpip] <https://github.com/mirage/mirage-tcpip>
[mnet] <https://github.com/robur-coop/mnet/blob/main/tests/simple.t>
[this tutorial] <https://robur-coop.github.io/mnet/>
Deployment
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C
`ptt' also tackles the deployment question. We have [an article]
presenting the "stateless" aspect of `ptt'. We'd also like to
(re)introduce [Albatross](github.com/robur-coop/albatross), our secure
unikernel orchestrator, and [Mollymawk], a web interface for deploying
unikernels (which is itself a unikernel).
More broadly, this is what [our cooperative] is working towards: we
really want to improve the user experience, whether you're a developer
or a deployer. We believe that actually developing, deploying, and
using our unikernels is the only way to get them adopted more
widely. So make sure to follow us on these projects too!
[an article] <https://blog.robur.coop/articles/2026-04-09-ptt.html>
[Mollymawk] <https://github.com/robur-coop/mollymawk/>
[our cooperative] <https://robur.coop>
Usage
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
Along the way, we found it really helpful to have a tool that lets you
track every stage of an email=E2=80=99s lifecycle. That=E2=80=99s how [`b=
laze'] came
about: a Swiss Army knife for handling emails.
It=E2=80=99s still experimental, but it already lets you:
=E2=80=A2 use our archive system (generate, read, index, etc.)
=E2=80=A2 handle other archives such as `mbox' or `maildir'
=E2=80=A2 communicate via the POP3 protocol
=E2=80=A2 sign and verify emails (DKIM and ARC)
=E2=80=A2 build emails from the command line
=E2=80=A2 send emails
=E2=80=A2 run a small local SMTP server
`blaze' is how we iterate on our library APIs and validate
implementations. It=E2=80=99s experimental, but it=E2=80=99s gradually tu=
rning into a
full email client.
[`blaze'] <https://github.com/dinosaure/blaze>
=E2=97=8A Archiving & Indexing
We'd also like to present the [stem] project, which extracts word
roots from a document (such as an email) and tokenises them to get
something analysable without the complexity of natural language. This
tokenisation is what powers our small [bm25] search engine. You can
see results [here].
This is also what drives our caml-list search engine, available as a
unikernel: [blame], which you can try at
<https://caml-list.robur.coop> (powered by [vif]).
Beyond search, there's also email indexing via Message-IDs. For that
we built [bancos]: a *persistent* radix tree in OCaml that supports
*parallel* access! More details [here].
Finally, our indexing system uses the PACKv2 format (the same one Git
uses to store objects), implemented by the [carton] library. It has
proven its stability through the [ocaml-git] project, so we decided to
reuse it for archiving emails (much like [public-inbox] did, though in
a different form).
[stem] <https://git.robur.coop/robur/stem>
[bm25] <https://en.wikipedia.org/wiki/Okapi_BM25>
[here]
<https://blog.robur.coop/articles/ptt_stem_and_search_engine.html>
[blame] <https://github.com/robur-coop/blame>
[vif] <https://github.com/robur-coop/vif>
[bancos] <https://github.com/robur-coop/bancos>
[here] <https://blog.robur.coop/articles/2025-18-12-bancos.html>
[carton] <https://github.com/robur-coop/carton>
[ocaml-git] <https://github.com/mirage/ocaml-git>
[public-inbox] <https://public-inbox.org/README>
Conclusion
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C
Thanks to all this work, OCaml now has a solid set of email-related
projects. This journey started back in 2016 and there's still a long
way to go, as we always aim to offer robu(r)st, battle-tested
solutions. Unlike some implementations in other languages (though we
are in discussion with folks in the Rust community), ours actually
adhere to the standards!
It may not seem like a big deal, and you won't see any major
difference when just exchanging emails, but we believe this approach
paves the way for a better internet. In the form of unikernels, it
represents a genuine reclaiming of the means of communication!
Mollymawk and Albatross orchestrating all virtual machines
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-al=
l-virtual-machines/17988/1>
Hannes Mehnert announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Dear everyone,
we just finished and deployed [Albatross] and [Mollymawk] to support
virtual machines that are not MirageOS unikernels.
The reasoning is simple: we embedded so many nice features (metrics,
console output, deploying via web UI, multi-tenant, startup
dependencies, restart-on-failure,..) that we really wanted to deploy
our non-MirageOS virtual machines as well with the same mechanism and
don't have duplicated code all over.
For the time being, it only supports FreeBSD BHyve, but let us know if
you're interested in other virtualization technologies and we will
prioritize that work!
We also wrote a brief blog article with screenshots:
<https://blog.robur.coop/articles/mollymawk-other.html>
[Albatross] <https://github.com/robur-coop/albatross>
[Mollymawk] <https://github.com/robur-coop/mollymawk>
OUPS meetup april 2026
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive: <https://discuss.ocaml.org/t/oups-meetup-april-2026/17989/1>
ancolie announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80
The next OUPS meetup will take place on *Wednesday, 29th of April*
2026. It will start at *6:30pm* at the *45 rue d'Ulm* in Paris. It
will be in the in the *Rataud amphitheater*.
:warning: It's not in Jussieu as usual but in ENS Ulm! If you're not
familiar with the place, there is a [map of the buildings].
Please, *[register on meetup ]* as soon as possible to let us know how
many pizza we should order.
For more details, you may check the [OUPS=E2=80=99 website ].
Moreover, we=E2=80=99d like to announce that the organizing team moved to=
the
[OCaml Zulip]. Feel free to contact us there if you=E2=80=99d like to sug=
gest
talks.
=E2=80=94
This time we=E2=80=99ll have the following talks:
*When Turing machines meet GADTs =E2=80=93 Florian Angeletti*
Have you ever wondered why one needs to write down explicit
unreachable clauses in a GADT-pattern matching? Or how much
computation one can sneak inside an OCaml type?
This talk proposes to answers those questions and more with a deep
dive into GADTs, the OCaml compiler implementation of the
exhaustiveness checking for pattern match, and how to best trick the
typechecker into finding the BB(3) champion by itself.
*Extending OCaml's pattern matching =E2=80=93 Yanni Lefki*
Pattern matching has been studied for decades and has been the subject
of extensive research and numerous extensions. Nevertheless, recent
language features=E2=80=94such as Rust=E2=80=99s if-let construct, and re=
cent work
such as Cheng and Parreaux (OOPSLA 2024), suggest that there is still
room for improvement. We propose a streamlined approach that unifies
pattern matching with extended forms of conditionals.
In particular, our prototype introduces binding-boolean-expressions,
which allow variables to be bound within pattern guards, within
if-conditions (and subsequently used in the then branch), and within
while-conditions (and used in the loop body). Our system also
incorporates Haskell-style views, enabling the definition of smart
deconstructors, the dual of smart constructors.
In this talk, we present an ML-like language equipped with evaluation
rules, typing rules, and a simple compilation scheme. We conclude with
a demonstration of our implementation: an OCaml PPX prototype that
parses an extended ML syntax exposing these constructs, type-checks
programs according to our (highly intuitive!) rules, and translates
them into a correct OCaml AST via our (non-optimizing) transformation.
=E2=80=94
After the talks there will be some pizzas offered by the [OCaml
Software Foundation] and later on we=E2=80=99ll move to a pub nearby as u=
sual.
[map of the buildings]
<https://www.ens.psl.eu/IMG/pdf/Plan_45ULM_SS.pdf>
[register on meetup ]
<https://www.meetup.com/ocaml-paris/events/314296893/>
[OUPS=E2=80=99 website ] <https://oups.frama.io>
[OCaml Zulip] <https://ocaml.zulipchat.com>
[OCaml Software Foundation] <https://ocaml-sf.org>
Stk 0.6 released
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive: <https://discuss.ocaml.org/t/ann-stk-0-6-released/17994/1>
Zoggy announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Hello,
Stk is a SDL-based graphical user interface toolkit. Its interface is
inspired by Gtk and should look familiar to developers using Lablgtk.
Stk 0.6 is available. Among changes listed [here], this release
introduces [Tooltips] and [handling of user's configuration],
including user-defined themes.
The `stk*' packages are available from my [personal opam repository].
[here] <https://zoggy.frama.io/ocaml-stk/posts/release-0.6.0.html>
[Tooltips]
<https://zoggy.frama.io/ocaml-stk/refdoc/stk/Stk/Tooltip/index.html>
[handling of user's configuration]
<https://zoggy.frama.io/ocaml-stk/doc-config.html>
[personal opam repository] <https://framagit.org/zoggy/opam-repository>
opam 2.5.1
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90
Archive: <https://discuss.ocaml.org/t/ann-opam-2-5-1/17997/1>
Kate announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Hi everyone,
opam 2.5.1 is now available. This release is fixing a security issue
([OSEC-2026-03]) and other minor things. /Thanks to [@andrew] for
reporting this issue./
We invite everyone to upgrade to 2.5.1 as soon as possible.
If you depend on the older opam package of your preferred
distribution, distributions such as Debian Stable have already started
backporting the relevant fix and the patched version should be
available there very soon.
You can read our [blog post] for relevant links and details.
[OSEC-2026-03]
<https://github.com/ocaml/security-advisories/blob/main/advisories/2026/OSE=
C-2026-03.md>
[@andrew] <https://github.com/andrew>
[blog post] <https://opam.ocaml.org/blog/opam-2-5-1/>
Try it!
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
The upgrade instructions are unchanged:
For Unix systems
bash -c "sh <(curl -fsSL
<https://opam.ocaml.org/install.sh>) =E2=80=93version 2.5.1"
or from PowerShell for Windows systems
Invoke-Expression "& { $(Invoke-RestMethod
<https://opam.ocaml.org/install.ps1>) } -Version 2.5.1"
Please report any issues to the [bug-tracker].
Happy hacking,
<> <> The opam team <> <> :camel:
[bug-tracker] <https://github.com/ocaml/opam/issues>
Restarting OCaml.jp: The OCaml Japan User Group
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-restarting-ocaml-jp-the-ocaml-japan-user=
-group/17998/1>
mt_caret announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80
Dear OCaml community,
We're excited to announce the relaunch of *OCaml.jp*
([https://ocaml.jp/]), the OCaml Japan User Group!
Our goal is to grow and energize the OCaml community in Japan by
bringing together users to foster broader adoption and deeper
engagement with OCaml across the country.
[https://ocaml.jp/] <https://ocaml.jp/>
Current Activities
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C
We've already kicked off a couple of initiatives:
=E2=80=A2 *OCaml Weekly News - Japanese Edition*: We're maintaining a Jap=
anese
translation of the OCaml Weekly News at [https://ocaml.jp/cwn-ja/],
making it easier for Japanese speakers to stay up to date with the
latest happenings in the OCaml ecosystem.
=E2=80=A2 *OCaml Meetup in Tokyo (August 2026)*: We are currently prepari=
ng to
host an OCaml Meetup in Tokyo this August, the first one in [over
ten years]! More details will be shared soon; please stay tuned!
[https://ocaml.jp/cwn-ja/] <https://ocaml.jp/cwn-ja/>
[over ten years] <https://ocaml.jp/events/>
Join Us!
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
We're using *Discord* as our primary communication platforms. Whether
you're based in Japan, are a Japanese-speaking OCaml enthusiast
anywhere in the world, or simply want to connect with the Japanese
OCaml community, we'd love to have you join us!
Please use the following link to join Discord:
[https://discord.gg/qQTbny8KF4]
We look forward to building a vibrant OCaml community in Japan
together. =E3=82=88=E3=82=8D=E3=81=97=E3=81=8F=E3=81=8A=E9=A1=98=E3=81=84=
=E3=81=97=E3=81=BE=E3=81=99=EF=BC=81
[https://discord.gg/qQTbny8KF4] <https://discord.gg/qQTbny8KF4>
Code navigation and search on Github
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-code-navigation-and-search-on-github/179=
99/1>
Pieter Goetschalckx announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=80=E2=94=80
GitHub is now using [tree-sitter-ocaml] for [code navigation] and
[code search].
=E2=80=A2 Code highlighting should be more accurate (compared to the old
TextMate grammar) and supports all features up to OCaml 5.4.
=E2=80=A2 There is a symbols side panel for each file.
=E2=80=A2 You can click on symbols to find definitions and references.
=E2=80=A2 You can [search for definitions].
=E2=80=A2 There is limited support for [nested structures].
They enabled it [a few months ago] already, but I forgot to post it
here.
The code navigation is not always 100% accurate, but good enough to be
helpful. If you encounter any issues with incorrectly highlighted
code, this could be a tree-sitter-ocaml issue.
[tree-sitter-ocaml] <https://github.com/tree-sitter/tree-sitter-ocaml>
[code navigation]
<https://docs.github.com/en/repositories/working-with-files/using-files/nav=
igating-code-on-github>
[code search]
<https://docs.github.com/en/search-github/github-code-search/understanding-=
github-code-search-syntax#symbol-qualifier>
[search for definitions]
<https://github.com/search?q=3Drepo%3Aocaml%2Focaml+def%3Afind&type=3Dcode>
[nested structures]
<https://github.com/search?q=3Drepo%3Aocaml%2Focaml+Make.t&type=3Dcode>
[a few months ago] <https://github.com/github/code-navigation/issues/14>
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/seeking-maintainers-for-our-ocaml-sip-server=
-grpc-and-http-2-libraries/18000/1>
Wojtek Czekalski announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80
As we're moving off OCaml at [dialo], we'd like to donate the
libraries we built to people who will properly maintain them. We built
a highly performant telephony system using OCaml, but as a small team
we ended up maintaining too much software for our liking.
We initially built a SIP server implementation in OCaml, which was a
perfect fit. We needed to connect it to the rest of our system in a
language agnostic way. We chose gRPC and that's where things got
difficult.
At a smaller scale our own buggy implementation of gRPC on top of [h2]
was good enough. Then we started scaling and at the same time
transitioned to OCaml 5.0. The combination of those factors resulted
in:
1. Performance regressions in 5.0 related to memory management, both
inside of app code, SIP stack, and inside of h2.
2. We needed a more robust implementation of gRPC to handle errors and
edge cases better.
Long story short we ended up:
1. Writing our own implementation of [http2]
2. Rewriting the gRPC library exclusively for eio to limit the scope
together with [decent codegen] and robust
Then, in late 2025, we had to add new features to the SIP server and
something inside us just broke. The SIP server had accumulated quite a
bit of legacy code over 3.5 years, so we wanted to rewrite some
parts. We were extremely excited to build the new architecture
centered around effects =E2=80=94 [only to discover that user-space effec=
ts
and concurrency libraries don't really work well together], since
callbacks lose their scope (duh). That was the final straw.
We decided to run two 1-week stints to try rewriting the service in
Rust and Go. We ended up choosing Rust. We still miss OCaml, but not
having to implement and maintain our own http2/grpc/sip stack is a
breath of fresh air.
So here we are =E2=80=94 we're gradually removing OCaml from our stack, a=
nd
that's why we'd like to donate:
=E2=80=A2 [ocaml-grpc] - the new code is on `dialo' branch, eio only at t=
he
moment, battle tested on production. It does have some bugs in it
but few and it's pretty solid.
=E2=80=A2 [haha (http2)] - overall good but could be better. We cancel fi=
bers
too often, it's a very low hanging fruit to make it much faster.
=E2=80=A2 Our SIP stack =E2=80=94 this is currently not open source, but =
we're happy
to share the source code with the right person or team.
Please write dms to me and feel free to ask me or @adamchol about
specifics.
[dialo] <https://dialo.ai/>
[h2] <https://github.com/anmonteiro/ocaml-h2>
[http2] <https://github.com/dialohq/haha>
[decent codegen]
<https://github.com/dialohq/ocaml-grpc/blob/dialo/examples/routeguide/src/c=
lient.ml>
[only to discover that user-space effects and concurrency libraries
don't really work well together]
<https://discuss.ocaml.org/t/effect-composability-actual-callstack-vs-synta=
ctic-scope/17536>
[ocaml-grpc] <https://github.com/dialohq/ocaml-grpc/tree/dialo>
[haha (http2)] <https://github.com/dialohq/haha>
ppx_mixins: slightly more elegant mixin syntax
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-ppx-mixins-slightly-more-elegant-mixin-s=
yntax/18001/1>
Sacha Ayoun announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Hello,
I've written a tiny ppx called [`ppx_mixins'] so that one can write:
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 type u [@@mixins Map.OrderedType + Printable]
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
which gets desugared to
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 type u
=E2=94=82 include Map.OrderedType with type t :=3D u
=E2=94=82 include Printable with type t :=3D u
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Not much but increases readability in a codebase that uses the "mixin"
pattern a lot
[`ppx_mixins'] <https://github.com/soteria-tools/ppx_mixins>
Constructing type signatures
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C
In the upcoming release, one can also write
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 module type M =3D [%mixins Map.OrderedType + Printable]
=E2=94=82 (* desugars to *)
=E2=94=82 module type M =3D sig=20
=E2=94=82 type t=20
=E2=94=82 include Map.OrderedType with type t :=3D t
=E2=94=82 include Printable with type t :=3D t
=E2=94=82 end
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Additional features
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C
One can also override other types, e.g.
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 type u [@@mixins Mappable(key =3D int; value :=3D v)]
=E2=94=82 (* desugars to *)
=E2=94=82 type u
=E2=94=82 include Mappable with type t :=3D u and type key =3D int and ty=
pe value :=3D v
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
Limitations
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C
=E2=80=A2 No support for parametric types, e.g. `with type 'a u =3D 'a v'
=E2=80=A2 No support for tuple and function types, e.g. `with type t =3D =
int ->
bool'
This is because the preprocessor parses the payload as an expression,
and these don't parse nicely a expressions. Deeper support (e.g. for
mixins with type parameters) would probably also require language
support.
Experience Report: Refining Dune=E2=80=99s Dependency Graph
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90
Archive:
<https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency=
-graph/18002/1>
Robin Bate Boerop announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80
*Refining Dune's Dependency Graph: Per-Module Library Filtering*
I've been working on improving Dune's inter-library dependency
tracking, and wanted to share the experience =E2=80=94 both the technical
details and what it's like as a first-time contributor to this large
open source OCaml project.
The Problem I Took On
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
When `libA' depends on `libB', Dune gives every module in `libA' a
glob dependency on /all/ `.cmi' files in `libB'. If any `.cmi' in
`libB' changes, every module in `libA' is recompiled =E2=80=94 even modul=
es
that never reference `libB'.
For projects with many libraries, this creates a cascade of
unnecessary recompilations. The issue that tracks this matter [#4572]
has been open since 2021.
[#4572] <https://github.com/ocaml/dune/issues/4572>
My Approach
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C
Dune already runs `ocamldep' to compute intra-library module
dependencies. The key insight: that same output tells us which
/libraries/ each module references, via their entry module names. We
can use this to filter both the build dependencies and the `-I~/'-H~
compiler flags per-module.
The implementation ([PR #14116] and [PR #14186]) works as follows:
1. For each module and its transitive intra-library dependencies, read
the `ocamldep' output (both `.ml' and `.mli')
2. Union all referenced module names, including `-open' flags
3. Map those names to libraries via a `Lib_index'
4. Transitively close the filtered library set via `Lib.closure'
5. Use the result for both hidden deps and `-I~/'-H~ compiler flags,
partitioning into direct (visible via `-I') and hidden (via `-H')
based on `requires_compile' membership
With both deps and flags filtered, a clean build will fail if a module
references a library it doesn't declare =E2=80=94 previously, overly-broad
`-I' flags could mask such errors.
[PR #14116] <https://github.com/ocaml/dune/pull/14116>
[PR #14186] <https://github.com/ocaml/dune/pull/14186>
A False Start
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
My first attempt ([PR #14021]) tried to implement the filtering in a
single PR without sufficient test coverage. It was closed after review
revealed that the approach was fragile in edge cases I hadn't
anticipated =E2=80=94 particularly around transparent module aliases and
virtual libraries.
[PR #14021] <https://github.com/ocaml/dune/pull/14021>
Challenges
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C
*Transparent module aliases.* OCaml's module alias mechanism means
`ocamldep' doesn't always report all libraries a module transitively
depends on. If `libB' has `module M =3D LibC.Something', and a module
in `libA' uses `LibB.M', `ocamldep' reports `LibB' but not
`LibC'. The fix: transitively close the filtered library set using
`Lib.closure', bounded by the compilation context.
*Root modules.* The `(root_module)' stanza creates a module that
implicitly aliases all libraries in the compilation context. When
`ocamldep' reports a reference to a root module, we can't determine
which underlying libraries are actually needed, so we fall back to
the full dependency set.
*Virtual libraries.* When virtual library implementations are present
in the compilation context, parameter libraries may not appear in
`requires_compile', so filtering could miss them. Another fallback
case.
*Menhir-generated modules.* These mock modules aren't in the
`ocamldep' dependency graph, so we skip filtering for them.
*Null build overhead.* The filtering reads `.d' files and computes
library closures per-module. On a fresh `dune' process (no memo
cache), this is new work on every build =E2=80=94 including null builds =
where
nothing changed. This is a real trade-off: better incremental rebuild
performance at the cost of some null-build overhead.
Prerequisite Test PRs
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
Before the implementation PRs, I submitted six test-only PRs to
document existing behavior and establish a safety net:
=E2=80=A2 [#14017] =E2=80=94 Baseline tests documenting current inter-lib=
rary
recompilation behavior
=E2=80=A2 [#14031] =E2=80=94 Test documenting module name shadowing betwe=
en stanzas
and libraries
=E2=80=A2 [#14100] =E2=80=94 Test verifying library file deps in compilat=
ion rules and
sandboxed builds
=E2=80=A2 [#14101] =E2=80=94 Test verifying transparent alias incremental=
build safety
=E2=80=A2 [#14129] =E2=80=94 Test verifying incremental builds with alias=
re-exported
libraries
=E2=80=A2 [#14178] =E2=80=94 Test documenting `ocamldep' behavior with tr=
ansparent
alias chains
This made the implementation PRs' diffs focused on the actual change,
and gave reviewers confidence that existing behavior was preserved. It
also helped me understand the edge cases that tripped up my first
attempt.
[#14017] <https://github.com/ocaml/dune/pull/14017>
[#14031] <https://github.com/ocaml/dune/pull/14031>
[#14100] <https://github.com/ocaml/dune/pull/14100>
[#14101] <https://github.com/ocaml/dune/pull/14101>
[#14129] <https://github.com/ocaml/dune/pull/14129>
[#14178] <https://github.com/ocaml/dune/pull/14178>
The Review Process
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C
The Dune maintainers ([@rgrinberg] and [@art-w]) provided thorough,
constructive reviews. Some highlights:
=E2=80=A2 Replacing my hand-rolled transitive closure with `Lib.closure' =
from
the existing library =E2=80=94 a cleaner approach I wouldn't have found
without familiarity with Dune's internals
=E2=80=A2 Identifying that both `.ml' and `.mli' ocamldep output need to =
be
read, since the interface can reference different libraries than the
implementation
=E2=80=A2 Suggesting per-module `-I~/'-H~ flag filtering, which makes cle=
an
builds more precise and improves caching
=E2=80=A2 Questioning every fallback case and special-cased module kind,
leading to simpler code
The PRs went through significant refactoring during review =E2=80=94 the =
final
versions are substantially tighter than the initial submissions.
[@rgrinberg] <https://github.com/rgrinberg>
[@art-w] <https://github.com/art-w>
What Could Be Better
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C
Working on this was a positive experience overall, but a few things
created friction:
*No way to benchmark before merging.* The null-build overhead question
came up late in the process. I discovered through manual benchmarking
that the change added \~70% to null build time =E2=80=94 a significant
regression. Dune's benchmark CI workflow runs only on pushes to main,
not on PRs. Contributor-accessible performance tooling would help
catch regressions before they land.
*Review momentum vs. rebasing.* The test PRs merged quickly, but the
implementation PR required multiple rounds of review over
days. Between rounds, main moves forward, requiring rebases that risk
introducing conflicts. The contributor carries the burden of keeping
branches fresh. This is compounded when PRs depend on each other =E2=80=
=94
every rebase of #14116 required rebasing #14186 as well. GitHub has
no first-class support for PR stacks, so this is manual and
error-prone. Of course, all GitHub-hosted repos suffer from this.
*Flaky CI*. Many CI runs had errors that were not related to my
code. It was often an upstream provider of an OCaml package that was
unreachable or faulty (temporarily). These problems often resolved
themselves, but caused day-long delays in the PR lifetimes. The
problem stems from the setup code that is run and re-run over and
over in CI jobs.
Reflections
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C
The Dune codebase is well-structured, with clear separation between
the build engine, rule generation, and scheduler. It is also of good
quality, making it feel like time spent on keeping the quality high is
worthwhile.
I found the cram test infrastructure good for testing. Each test
scenario is a self-contained shell script with expected output, making
it easy to document and verify exact recompilation behavior. It
inspires confidence in the code.
The maintainers have been responsive and the review process, while
slowed by thoroughness, is collaborative and professional. Thank you,
maintainers!
Steffen Smolka then replied
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80
GitHub has no first-class support for PR stacks
It does now: <https://github.github.com/gh-stack/>
First beta release of OCaml 5.5.0
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/first-beta-release-of-ocaml-5-5-0/18006/1>
octachron announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80
With most developer tools available and the good stability of the
compiler, I am happy to announce the first beta release of OCaml
5.5.0.
Compared to the last alpha, this new version improves the manpage for
ocamlopt and fixes:
=E2=80=A2 two runtime bugs (for ephemerons and the bytecode interpreter)
=E2=80=A2 two type system bugs (for classes and module-dependent function=
s)
=E2=80=A2 three warning or error message bugs
(See the Changelog below for a full list).
Concerning the associated compiler tools, most of them are already
available (as least in a preview version), and there are patches in
progress for the remaining ones. You can track the last remaining
update efforts on the [release readiness meta-issue].
Thus, it should be safe to test your libraries and programs with the
new version OCaml 5.5.0 version in preparation of the final release.
If everything goes well, we might see a release in May.
If you find any bugs, please report them to the [GitHub issue
tracker].
If you are interested by the full list of new features and bug fixes,
the [changelog for OCaml 5.5.0] is the most up-to-date resource.
Happy hacking, Florian Angeletti for the OCaml team.
[release readiness meta-issue]
<https://github.com/ocaml/opam-repository/issues/29463>
[GitHub issue tracker] <https://github.com/ocaml/ocaml/issues>
[changelog for OCaml 5.5.0]
<https://github.com/ocaml/ocaml/blob/5.5/Changes>
Installation Instructions
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
The base compiler can be installed as an opam switch with the
following commands on opam 2.1 and later:
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 opam update
=E2=94=82 opam switch create 5.5.0~beta1
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
The source code for the beta is also available at these addresses:
=E2=80=A2 GitHub: <https://github.com/ocaml/ocaml/archive/5.5.0-beta1.tar=
.gz>
=E2=80=A2 OCaml archives at Inria:
<https://caml.inria.fr/pub/distrib/ocaml-5.5/ocaml-5.5.0~beta1.tar.gz>
Fine-Tuned Compiler Configuration
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C
If you want to tweak the configuration of the compiler, you can switch
to the option variant with:
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 opam update
=E2=94=82 opam switch create <switch_name> ocaml-variants.5.5.0~beta1+opt=
ions <option_list>
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
where `option_list' is a space separated list of `ocaml-option-*'
packages. For instance, for a flambda and no-flat-float-array switch:
=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
=E2=94=82 opam switch create 5.5.0~beta1+flambda+nffa ocaml-variants.5.5.=
0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array
=E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80
All available options can be listed with `opam search ocaml-option'.
Changes compared to the last alpha
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C
=E2=97=8A Documentation update
=E2=80=A2 [#14684]: Improve ocamlopt's manual page (Samuel Hym, review by
Florian Angeletti)
[#14684] <https://github.com/ocaml/ocaml/issues/14684>
=E2=97=8A Runtime fixes
=E2=80=A2 [#14644], [#14647]: Fix a bug related to unhandled effects in
bytecode. (Vincent Laviron, report by Thibaut Mattio, review by
Nicol=C3=A1s Ojeda B=C3=A4r, Stephen Dolan and Olivier Nicole)
=E2=80=A2 [#14349], [#14718]: runtime, fix in the orphaning of ephemerons
(Gabriel Scherer, review by Olivier Nicole and Damien Doligez,
report by Jan Midtgaard)
[#14644] <https://github.com/ocaml/ocaml/issues/14644>
[#14647] <https://github.com/ocaml/ocaml/issues/14647>
[#14349] <https://github.com/ocaml/ocaml/issues/14349>
[#14718] <https://github.com/ocaml/ocaml/issues/14718>
=E2=97=8A Type system fixes
=E2=80=A2 [#14557], [#12150], [#14696]: ensure that the self type of class
cannot escape through type constraints. (Leo White, review by
Florian Angeletti)
=E2=80=A2 [#14667]: enable application related warnings for module-depend=
ent
functions (Florian Angeletti, review by Gabriel Scherer)
[#14557] <https://github.com/ocaml/ocaml/issues/14557>
[#12150] <https://github.com/ocaml/ocaml/issues/12150>
[#14696] <https://github.com/ocaml/ocaml/issues/14696>
[#14667] <https://github.com/ocaml/ocaml/issues/14667>
=E2=97=8A Error messages and warning fixes
=E2=80=A2 [#14690]: Fix `Name_type_mismatch' error message when the expec=
ted
type is an alias: print the expanded path on the right-hand side of
the equality, not the alias twice. (Weixie Cui, review by Florian
Angeletti)
=E2=80=A2 [#14719], [#14721]: compute arity correctly for module-dependent
function (Florian Angeletti, report by Jeremy Yallop, review by
Stefan Muenzel)
=E2=80=A2 [#14655], [#14691]: check for size overflow in caml_ba_reshape
(Stephen Dolan, review by Xavier Leroy)
[#14690] <https://github.com/ocaml/ocaml/issues/14690>
[#14719] <https://github.com/ocaml/ocaml/issues/14719>
[#14721] <https://github.com/ocaml/ocaml/issues/14721>
[#14655] <https://github.com/ocaml/ocaml/issues/14655>
[#14691] <https://github.com/ocaml/ocaml/issues/14691>
ocgtk 0.1: OCaml bindings for GTK 4 (preview release)
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90
Archive:
<https://discuss.ocaml.org/t/ann-ocgtk-0-1-ocaml-bindings-for-gtk-4-previ=
ew-release/17944/5>
Continuing this thread, Chris Armstrong announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80
/ocgtk preview1 release has landed in opam./
(preview0 was abandoned as considerable work was required to get it
building on other Linux distributions and Mac). A special thanks to
@jmid for helping me get it over the line.
In addition to the features above, it includes:
=E2=80=A2 Extended support for more GLib types, including integer primiti=
ves
(guint8, int16, guint32, etc) and lists (GLib.SList and GLib.List)
=E2=80=A2 Gobject interfaces
The combination of the above enables more methods to be generated
(that were previously excluded) when they include those types in their
parameters and/or return types, opening up much more of the API
surface of GTK (and related libraries).
*Next steps*: my focus now is on internal cleanup and reorganisation
to better structure the tests and split gir_gen (the GObject code
generator) into a seperate dune project. This will reduce the
dependency list considerably and enable targeting earlier OCaml
versions, as well as reducing release headaches related to gir_gen
(which is not required by packages just using ocgtk)
Old CWN
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90
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] <mailto:[email protected]>
[the archive] <https://alan.petitepomme.net/cwn/>
[RSS feed of the archives] <https://alan.petitepomme.net/cwn/cwn.rss>
[caml-list] <https://sympa.inria.fr/sympa/info/caml-list>
[Alan Schmitt] <https://alan.petitepomme.net/>
--==-=-=
Content-Type: text/html; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
<?xml version=3D"1.0" encoding=3D"utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns=3D"http://www.w3.org/1999/xhtml" lang=3D"en" xml:lang=3D"en">
<head>
<!-- 2026-04-21 Tue 11:32 -->
<meta http-equiv=3D"Content-Type" content=3D"text/html;charset=3Dutf-8" />
<meta name=3D"viewport" content=3D"width=3Ddevice-width, initial-scale=3D1"=
/>
<title>OCaml Weekly News</title>
<meta name=3D"generator" content=3D"Org Mode" />
<style type=3D"text/css">
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-c:before { content: 'C'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'JavaScript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr {
font-size: smaller;
@supports (content: attr(data-linenr)) {
visibility: hidden;
&::before { content: attr(data-linenr); visibility: visible; }
}
}
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<style type=3D"text/css">#table-of-contents h2 { display: none } .title { d=
isplay: none } .authorname { text-align: right }</style>
<style type=3D"text/css">.outline-2 {border-top: 1px solid black;}</style>
</head>
<body>
<div id=3D"content" class=3D"content">
<h1 class=3D"title">OCaml Weekly News</h1>
<p>
<a href=3D"https://alan.petitepomme.net/cwn/2026.04.14.html">Previous Week<=
/a> <a href=3D"https://alan.petitepomme.net/cwn/index.html">Up</a> <a href=
=3D"https://alan.petitepomme.net/cwn/2026.04.28.html">Next Week</a>
</p>
<p>
Hello
</p>
<p>
Here is the latest OCaml Weekly News, for the week of April 14 to 21, 2026.
</p>
<div id=3D"table-of-contents" role=3D"doc-toc">
<h2>Table of Contents</h2>
<div id=3D"text-table-of-contents" role=3D"doc-toc">
<ul>
<li><a href=3D"#1">http-date v0.2 =E2=80=94 Zero-dependency HTTP date parsi=
ng for OCaml</a></li>
<li><a href=3D"#2">Caqti 2.3.0</a></li>
<li><a href=3D"#3">layoutz 0.1.0 =F0=9F=AA=B6 - Zero-dep Elm-style TUIs and=
terminal plots for your OCaml apps</a></li>
<li><a href=3D"#4">Dune 3.22</a></li>
<li><a href=3D"#5">ptt, a mailing list system as unikernel</a></li>
<li><a href=3D"#6">Mollymawk and Albatross orchestrating all virtual machin=
es</a></li>
<li><a href=3D"#7">OUPS meetup april 2026</a></li>
<li><a href=3D"#8">Stk 0.6 released</a></li>
<li><a href=3D"#9">opam 2.5.1</a></li>
<li><a href=3D"#10">Restarting OCaml.jp: The OCaml Japan User Group</a></li>
<li><a href=3D"#11">Code navigation and search on Github</a></li>
<li><a href=3D"#12">Seeking maintainers for our OCaml SIP server, gRPC, and=
HTTP/2 libraries</a></li>
<li><a href=3D"#13">ppx_mixins: slightly more elegant mixin syntax</a></li>
<li><a href=3D"#14">Experience Report: Refining Dune=E2=80=99s Dependency G=
raph</a></li>
<li><a href=3D"#15">First beta release of OCaml 5.5.0</a></li>
<li><a href=3D"#16">ocgtk 0.1: OCaml bindings for GTK 4 (preview release)</=
a></li>
<li><a href=3D"#orgc3cc6cf">Old CWN</a></li>
</ul>
</div>
</div>
<div id=3D"outline-container-1" class=3D"outline-2">
<h2 id=3D"1">http-date v0.2 =E2=80=94 Zero-dependency HTTP date parsing for=
OCaml</h2>
<div class=3D"outline-text-2" id=3D"text-1">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-http-date-v0-2-zero-dep=
endency-http-date-parsing-for-ocaml/17984/1">https://discuss.ocaml.org/t/an=
n-http-date-v0-2-zero-dependency-http-date-parsing-for-ocaml/17984/1</a>
</p>
</div>
<div id=3D"outline-container-org8bda44d" class=3D"outline-3">
<h3 id=3D"org8bda44d">Bikal Lem announced</h3>
<div class=3D"outline-text-3" id=3D"text-org8bda44d">
<p>
I just released v0.2 of http-date, an RFC 9110 compliant HTTP datetime deco=
der/encoder for OCaml.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20
</p>
<p>
This is a major rewrite from v0.1. Here's what changed:=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20
</p>
<p>
Zero dependencies =E2=80=94 Replaced the ocamllex/menhir parser with a hand=
-written implementation and removed the ptime=20=20=20=20=20=20=20
dependency entirely. The library now only requires ocaml and dune.
</p>
<p>
New type-safe API =E2=80=94 The parsed result is now a polymorphic variant =
tagged by format (IMF,=20
RFC850, `ASCTIME), so you=20=20=20=20
always know which HTTP date format was parsed. The dayname, date, time, and=
datetime types are all exposed in the
public API.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20
</p>
<p>
Serious testing =E2=80=94 Added property-based tests with alcobar and AFL f=
uzz testing infrastructure to build confidence in
the hand-written parser.
</p>
<p>
If you're working with HTTP headers in OCaml, give it a try:=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20
</p>
<p>
opam install http-date=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20
</p>
<p>
<a href=3D"https://github.com/bikallem/http-date">https://github.com/bikall=
em/http-date</a>
</p>
</div>
</div>
</div>
<div id=3D"outline-container-2" class=3D"outline-2">
<h2 id=3D"2">Caqti 2.3.0</h2>
<div class=3D"outline-text-2" id=3D"text-2">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-caqti-2-3-0/17985/1">ht=
tps://discuss.ocaml.org/t/ann-caqti-2-3-0/17985/1</a>
</p>
</div>
<div id=3D"outline-container-orgd95ea0b" class=3D"outline-3">
<h3 id=3D"orgd95ea0b">Petter A. Urkedal announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgd95ea0b">
<p>
I would like to announce the release of <a href=3D"https://github.com/paurk=
edal/ocaml-caqti">Caqti</a> 2.3.0.
</p>
<p>
TL;DR: Consider adding the <code>caqti.classic</code> to your link line (av=
ailable since this version). It currently only re-exports the <code>caqti<=
/code> library, but will be replaced by a compatibility layer for the Caqti=
2 API in Caqti 3 to allow incremental migration.
</p>
</div>
<div id=3D"outline-container-orga52d7a5" class=3D"outline-4">
<h4 id=3D"orga52d7a5">Release Notes</h4>
<div class=3D"outline-text-4" id=3D"text-orga52d7a5">
<p>
Note that some of the new features of this release are only accessible
through the still unstable <code>caqti.template</code> library, which will =
soon be
stabilized as part of an upcoming Caqti 3 API. Due to adjustments to module
names, switching to <code>caqti.template</code> will not ensure future comp=
atibility.
Instead, users are encouraged to add the new <code>caqti.classic</code> to =
their
dependencies to ease migration to Caqti 3.
</p>
<ul class=3D"org-ul">
<li>Added an alias <code>caqti.classic</code> for the <code>caqti</code> li=
brary. This will be
turned into a library providing compatibility with the current Caqti 2
API when Caqti 3 is released. The two APIs can be used side-by-side to
allow incremental migration.</li>
<li>The dialect descriptor for MariaDB in <code>caqti.template</code> now p=
rovides the
server version.</li>
<li>Added <code>Query.parens</code>, <code>Query.litf</code>, <code>Query.v=
ars</code>, <code>Row_type.fields</code> to
the <code>caqti.template</code> library.</li>
<li>Revised the interface for creating row types to allow instantiating
parametric types applicatively. Before this change, each application of
a function representing a parametric type would generate a new type ID
even when applied to the same type parameter argument. The key part of
this interface is the <code>Caqti_template.Constructor_type</code> module.<=
/li>
<li>The query functions provided to request templates are now memoized, so
that they are only called once per dialect. This is meant as an
optimization; it's still good practise to avoid side-effects here.</li>
<li>The new function <code>Query.with_pos_of</code> allows query generators=
to add
source locations to the syntax tree, which will be emitted as SQL
comments in the query string if the <code>enable_query_annotations</code> i=
s set.
This should simplify debugging when the query is assembled from
different parts of the application code.</li>
<li>The still unstable <code>caqti.template</code> library now supports mul=
tiple
statements in a single request template, sent opportunistically as a
single query where allowed. This is still experimental.</li>
<li>Fixed package scoping of shim rules for sqlite3 (#133 by mefyl).</li>
<li>Fixed the error classification for the SQLite3 driver (#132).</li>
<li>Fixed reconnect after connection loss for PostgreSQL.</li>
</ul>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-3" class=3D"outline-2">
<h2 id=3D"3">layoutz 0.1.0 =F0=9F=AA=B6 - Zero-dep Elm-style TUIs and termi=
nal plots for your OCaml apps</h2>
<div class=3D"outline-text-2" id=3D"text-3">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-layoutz-0-1-0-zero-dep-=
elm-style-tuis-terminal-plots-for-your-ocaml-apps/17986/1">https://discuss.=
ocaml.org/t/ann-layoutz-0-1-0-zero-dep-elm-style-tuis-terminal-plots-for-yo=
ur-ocaml-apps/17986/1</a>
</p>
</div>
<div id=3D"outline-container-orgcbccdd1" class=3D"outline-3">
<h3 id=3D"orgcbccdd1">Matthieu Court announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgcbccdd1">
<p>
Hello all! Thanks for your feedback last time - <a href=3D"https://github.c=
om/mattlianje/layoutz/tree/master/layoutz-ocaml">layoutz</a> now has an Elm=
-style TUI runtime (quite <a href=3D"https://github.com/mattlianje/layoutz/=
tree/master/layoutz-ocaml#faq">different in spirit</a> than (the excellent)=
Minttea) =E2=80=A6 a smoothed API .. and terminal plot built-ins.
</p>
<p>
Looking for feedback! Many thanks
</p>
</div>
</div>
</div>
<div id=3D"outline-container-4" class=3D"outline-2">
<h2 id=3D"4">Dune 3.22</h2>
<div class=3D"outline-text-2" id=3D"text-4">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-dune-3-22/17912/3">http=
s://discuss.ocaml.org/t/ann-dune-3-22/17912/3</a>
</p>
</div>
<div id=3D"outline-container-org34ce07b" class=3D"outline-3">
<h3 id=3D"org34ce07b">Continuing this thread, Shon announced</h3>
<div class=3D"outline-text-3" id=3D"text-org34ce07b">
<p>
The Dune team is pleased to announce <a href=3D"https://github.com/ocaml/du=
ne/releases/tag/3.22.2">the release of dune 3.22.2</a>.
</p>
<p>
This is a patch release consisting of bug fixes. See <a href=3D"https://git=
hub.com/ocaml/dune/releases/tag/3.22.2">the full changelog</a> for all the =
changes and for attribution to the contributors who made it all possible. T=
hank you, contributors!
</p>
<p>
If you encounter a problem with this release, please report it in [our issue
</p>
</div>
<div id=3D"outline-container-org5781837" class=3D"outline-4">
<h4 id=3D"org5781837">Fixed</h4>
<div class=3D"outline-text-4" id=3D"text-org5781837">
<ul class=3D"org-ul">
<li>Revert the change in behavior of <code>--diff-command</code> back to 3.=
21. Non-existent files are now passed to this command instead of being repl=
aced with /dev/null (<a href=3D"https://github.com/ocaml/dune/pull/14098">#=
14098</a>, fixes 13891, <a href=3D"https://github.com/rgrinberg">@rgrinberg=
</a>)</li>
</ul>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-5" class=3D"outline-2">
<h2 id=3D"5">ptt, a mailing list system as unikernel</h2>
<div class=3D"outline-text-2" id=3D"text-5">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-ptt-a-mailing-list-syst=
em-as-unikernel/17987/1">https://discuss.ocaml.org/t/ann-ptt-a-mailing-list=
-system-as-unikernel/17987/1</a>
</p>
</div>
<div id=3D"outline-container-orgfae88f2" class=3D"outline-3">
<h3 id=3D"orgfae88f2">Calascibetta Romain announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgfae88f2">
<p>
Hey! We just launched a new mailing list powered entirely by OCaml unikerne=
ls. The website (itself a unikernel) is at <a href=3D"https://mailingl.st">=
https://mailingl.st</a>. You can subscribe to [email protected] by sending an=
email to [email protected] if you're interested in the development=
and deployment of SMTP-related unikernels.
</p>
<p>
Fair warning: this is still a <b>public test</b> mailing list for now. In t=
he long run, it will focus on our ptt project.
</p>
</div>
<div id=3D"outline-container-org2d30303" class=3D"outline-4">
<h4 id=3D"org2d30303">The SMTP protocol: a long and winding road!</h4>
<div class=3D"outline-text-4" id=3D"text-org2d30303">
</div>
<ul class=3D"org-ul">
<li><a id=3D"org90d5109"></a>In the beginning, email<br />
<div class=3D"outline-text-5" id=3D"text-org90d5109">
<p>
It all started with <a href=3D"https://github.com/mirage/mrmime">Mr.MIME</a=
>, our library for decoding and encoding emails. It's a synthesis of the re=
levant RFCs, but more importantly it's been battle-tested against real-worl=
d emails from the IEEE, <a href=3D"https://www.cs.cmu.edu/~enron/">Enron</a=
>, <a href=3D"https://yhbt.net/lore/kvm/">KVM</a> and, most recently, the <=
a href=3D"https://discuss.ocaml.org/t/is-there-a-public-archive-for-the-cam=
l-list/16374/6?u=3Ddinosaure">caml-list</a>.
</p>
<p>
This work also let us build <a href=3D"https://github.com/mirage/hamlet">Ha=
mlet</a>, a database of valid random emails generated using a fuzzer.
</p>
<p>
Under the hood, Mr.MIME relies on <a href=3D"https://github.com/dinosaure/u=
nstrctrd">unstrctrd</a> for decoding the most general form of values found =
in an email (with internationalisation support via <a href=3D"https://githu=
b.com/mirage/rosetta">rosetta</a>) and <a href=3D"https://github.com/dinosa=
ure/prettym">prettym</a> for encoding emails while respecting SMTP constrai=
nts and (Comment) Folding Whitespace handling.
</p>
</div>
</li>
<li><a id=3D"orgf11f880"></a>Next, the protocol<br />
<div class=3D"outline-text-5" id=3D"text-orgf11f880">
<p>
Then came <a href=3D"https://github.com/mirage/colombe">colombe</a>, our OC=
aml implementation of the SMTP protocol. It uses <a href=3D"https://github.=
com/mirleft/ocaml-tls">ocaml-tls</a> for <code>STARTTLS</code> support.
</p>
<p>
The protocol is supposedly "simple" (though the Internet always has surpris=
es in store), but from day one we designed colombe to be independent of any=
scheduler and network layer. That way it slots right into unikernels witho=
ut friction.
</p>
</div>
</li>
<li><a id=3D"org39c65b9"></a>Finally, legitimacy<br />
<div class=3D"outline-text-5" id=3D"text-org39c65b9">
<p>
On top of these core components, we built several email security layers:
</p>
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/mirage/ocaml-dkim">ocaml-dkim</a> handles=
signing and verifying email integrity in a streaming fashion (both for ver=
ification and signature generation)</li>
<li><a href=3D"https://github.com/mirage/uspf">uspf</a> verifies sender ide=
ntity and, like most of our libraries, stays independent of any scheduler o=
r DNS implementation</li>
<li><a href=3D"https://github.com/dinosaure/ocaml-dmarc">ocaml-dmarc</a> au=
tomates DKIM and SPF verification, stamps emails with the result, and check=
s alignment across a domain name</li>
<li>[ocaml-arc](github.com/robur-coop/ocaml-arc) lets you verify and sign e=
mails to complete a chain of trust when an email passes through multiple SM=
TP servers (which is exactly what happens with a mailing list)</li>
</ul>
<p>
We wrote a short article about all of this <a href=3D"https://blog.robur.co=
op/articles/2025-04-23-email-verification.html">here</a>.
</p>
</div>
</li>
</ul>
</div>
<div id=3D"outline-container-orga817fa1" class=3D"outline-4">
<h4 id=3D"orga817fa1">All in the form of unikernels</h4>
<div class=3D"outline-text-4" id=3D"text-orga817fa1">
<p>
Our first experiments already showed that we <a href=3D"https://mirage.io/b=
log/2022-04-01-Mr-MIME">could handle emails</a> with MirageOS unikernels. B=
ut we also hit real limitations: memory leaks, security vulnerabilities, an=
d build issues.
</p>
<p>
So we decided to start fresh, and take the opportunity to fully embrace OCa=
ml 5 and effects. We rebuilt the key pieces from scratch:
</p>
<ul class=3D"org-ul">
<li>a new effect-based scheduler: <a href=3D"https://github.com/robur-coop/=
miou">Miou</a>/<a href=3D"https://github.com/robur-coop/mkernel">Mkernel</a=
></li>
<li>a much more complete TCP/IP stack: <a href=3D"https://github.com/robur-=
coop/mnet">Mnet</a></li>
<li>a new FAT32 file system: <a href=3D"https://github.com/robur-coop/mfat"=
>Mfat</a></li>
</ul>
<p>
<code>ptt</code> is built on this new stack, and so far we haven=E2=80=99t =
observed any memory leaks (thanks to <a href=3D"https://git.robur.coop/robu=
r/miou-solo5-memtrace">mkernel-memtrace</a> for tracing memory usage, viewa=
ble via <a href=3D"https://github.com/janestreet/memtrace/">memtrace-viewer=
</a>). The CVEs related to <a href=3D"https://github.com/mirage/mirage-tcpi=
p">mirage-tcpip</a> were taken into account during ~mnet~=E2=80=99s develop=
ment, and the build story is much simpler now. A GitHub action can build an=
d actually run the unikernel to test it, as you can see with <a href=3D"htt=
ps://github.com/robur-coop/mnet/blob/main/tests/simple.t">mnet</a>.
</p>
<p>
Other unikernels using this approach are available too. If you=E2=80=99re c=
urious, check out <a href=3D"https://robur-coop.github.io/mnet/">this tutor=
ial</a> on creating a unikernel in OCaml.
</p>
</div>
</div>
<div id=3D"outline-container-org29f2635" class=3D"outline-4">
<h4 id=3D"org29f2635">Deployment</h4>
<div class=3D"outline-text-4" id=3D"text-org29f2635">
<p>
<code>ptt</code> also tackles the deployment question. We have <a href=3D"h=
ttps://blog.robur.coop/articles/2026-04-09-ptt.html">an article</a> present=
ing the "stateless" aspect of <code>ptt</code>. We'd also like to (re)intro=
duce [Albatross](github.com/robur-coop/albatross), our secure unikernel orc=
hestrator, and <a href=3D"https://github.com/robur-coop/mollymawk/">Mollyma=
wk</a>, a web interface for deploying unikernels (which is itself a unikern=
el).
</p>
<p>
More broadly, this is what <a href=3D"https://robur.coop">our cooperative</=
a> is working towards: we really want to improve the user experience, wheth=
er you're a developer or a deployer. We believe that actually developing, d=
eploying, and using our unikernels is the only way to get them adopted more=
widely. So make sure to follow us on these projects too!
</p>
</div>
</div>
<div id=3D"outline-container-orge2e975b" class=3D"outline-4">
<h4 id=3D"orge2e975b">Usage</h4>
<div class=3D"outline-text-4" id=3D"text-orge2e975b">
<p>
Along the way, we found it really helpful to have a tool that lets you trac=
k every stage of an email=E2=80=99s lifecycle. That=E2=80=99s how <a href=
=3D"https://github.com/dinosaure/blaze"><code>blaze</code></a> came about: =
a Swiss Army knife for handling emails.
</p>
<p>
It=E2=80=99s still experimental, but it already lets you:
</p>
<ul class=3D"org-ul">
<li>use our archive system (generate, read, index, etc.)</li>
<li>handle other archives such as <code>mbox</code> or <code>maildir</code>=
</li>
<li>communicate via the POP3 protocol</li>
<li>sign and verify emails (DKIM and ARC)</li>
<li>build emails from the command line</li>
<li>send emails</li>
<li>run a small local SMTP server</li>
</ul>
<p>
<code>blaze</code> is how we iterate on our library APIs and validate imple=
mentations. It=E2=80=99s experimental, but it=E2=80=99s gradually turning i=
nto a full email client.
</p>
</div>
<ul class=3D"org-ul">
<li><a id=3D"orgc67e720"></a>Archiving & Indexing<br />
<div class=3D"outline-text-5" id=3D"text-orgc67e720">
<p>
We'd also like to present the <a href=3D"https://git.robur.coop/robur/stem"=
>stem</a> project, which extracts word roots from a document (such as an em=
ail) and tokenises them to get something analysable without the complexity =
of natural language. This tokenisation is what powers our small <a href=3D"=
https://en.wikipedia.org/wiki/Okapi_BM25">bm25</a> search engine. You can s=
ee results <a href=3D"https://blog.robur.coop/articles/ptt_stem_and_search_=
engine.html">here</a>.
</p>
<p>
This is also what drives our caml-list search engine, available as a uniker=
nel: <a href=3D"https://github.com/robur-coop/blame">blame</a>, which you c=
an try at <a href=3D"https://caml-list.robur.coop">https://caml-list.robur.=
coop</a> (powered by <a href=3D"https://github.com/robur-coop/vif">vif</a>).
</p>
<p>
Beyond search, there's also email indexing via Message-IDs. For that we bui=
lt <a href=3D"https://github.com/robur-coop/bancos">bancos</a>: a <b>persis=
tent</b> radix tree in OCaml that supports <b>parallel</b> access! More det=
ails <a href=3D"https://blog.robur.coop/articles/2025-18-12-bancos.html">he=
re</a>.
</p>
<p>
Finally, our indexing system uses the PACKv2 format (the same one Git uses =
to store objects), implemented by the <a href=3D"https://github.com/robur-c=
oop/carton">carton</a> library. It has proven its stability through the <a =
href=3D"https://github.com/mirage/ocaml-git">ocaml-git</a> project, so we d=
ecided to reuse it for archiving emails (much like <a href=3D"https://publi=
c-inbox.org/README">public-inbox</a> did, though in a different form).
</p>
</div>
</li>
</ul>
</div>
<div id=3D"outline-container-org1105639" class=3D"outline-4">
<h4 id=3D"org1105639">Conclusion</h4>
<div class=3D"outline-text-4" id=3D"text-org1105639">
<p>
Thanks to all this work, OCaml now has a solid set of email-related project=
s. This journey started back in 2016 and there's still a long way to go, as=
we always aim to offer robu(r)st, battle-tested solutions. Unlike some imp=
lementations in other languages (though we are in discussion with folks in =
the Rust community), ours actually adhere to the standards!
</p>
<p>
It may not seem like a big deal, and you won't see any major difference whe=
n just exchanging emails, but we believe this approach paves the way for a =
better internet. In the form of unikernels, it represents a genuine reclaim=
ing of the means of communication!
</p>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-6" class=3D"outline-2">
<h2 id=3D"6">Mollymawk and Albatross orchestrating all virtual machines</h2>
<div class=3D"outline-text-2" id=3D"text-6">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-mollymawk-and-albatross=
-orchestrating-all-virtual-machines/17988/1">https://discuss.ocaml.org/t/an=
n-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988/1</a>
</p>
</div>
<div id=3D"outline-container-org36ef5bb" class=3D"outline-3">
<h3 id=3D"org36ef5bb">Hannes Mehnert announced</h3>
<div class=3D"outline-text-3" id=3D"text-org36ef5bb">
<p>
Dear everyone,
</p>
<p>
we just finished and deployed <a href=3D"https://github.com/robur-coop/alba=
tross">Albatross</a> and <a href=3D"https://github.com/robur-coop/mollymawk=
">Mollymawk</a> to support virtual machines that are not MirageOS unikernel=
s.
</p>
<p>
The reasoning is simple: we embedded so many nice features (metrics, consol=
e output, deploying via web UI, multi-tenant, startup dependencies, restart=
-on-failure,..) that we really wanted to deploy our non-MirageOS virtual ma=
chines as well with the same mechanism and don't have duplicated code all o=
ver.
</p>
<p>
For the time being, it only supports FreeBSD BHyve, but let us know if you'=
re interested in other virtualization technologies and we will prioritize t=
hat work!
</p>
<p>
We also wrote a brief blog article with screenshots: <a href=3D"https://blo=
g.robur.coop/articles/mollymawk-other.html">https://blog.robur.coop/article=
s/mollymawk-other.html</a>
</p>
</div>
</div>
</div>
<div id=3D"outline-container-7" class=3D"outline-2">
<h2 id=3D"7">OUPS meetup april 2026</h2>
<div class=3D"outline-text-2" id=3D"text-7">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/oups-meetup-april-2026/1798=
9/1">https://discuss.ocaml.org/t/oups-meetup-april-2026/17989/1</a>
</p>
</div>
<div id=3D"outline-container-orgc372f54" class=3D"outline-3">
<h3 id=3D"orgc372f54">ancolie announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgc372f54">
<p>
The next OUPS meetup will take place on <b>Wednesday, 29th of April</b> 202=
6. It will start at <b>6:30pm</b> at the <b>45 rue d'Ulm</b> in Paris. It w=
ill be in the in the <b>Rataud amphitheater</b>.
</p>
<p>
:warning: It's not in Jussieu as usual but in ENS Ulm! If you're not famili=
ar with the place, there is a <a href=3D"https://www.ens.psl.eu/IMG/pdf/Pla=
n_45ULM_SS.pdf">map of the buildings</a>.
</p>
<p>
Please, <b><a href=3D"https://www.meetup.com/ocaml-paris/events/314296893/"=
>register on meetup </a></b> as soon as possible to let us know how many pi=
zza we should order.
</p>
<p>
For more details, you may check the <a href=3D"https://oups.frama.io">OUPS=
=E2=80=99 website </a>.
</p>
<p>
Moreover, we=E2=80=99d like to announce that the organizing team moved to t=
he <a href=3D"https://ocaml.zulipchat.com">OCaml Zulip</a>. Feel free to co=
ntact us there if you=E2=80=99d like to suggest talks.
</p>
<p>
—
</p>
<p>
This time we=E2=80=99ll have the following talks:
</p>
<p>
<b>When Turing machines meet GADTs – Florian Angeletti</b>
</p>
<p>
Have you ever wondered why one needs to write down explicit
unreachable clauses in a GADT-pattern matching? Or how much
computation one can sneak inside an OCaml type?
</p>
<p>
This talk proposes to answers those questions and more with a deep dive
into GADTs, the OCaml compiler implementation of the exhaustiveness
checking for pattern match, and how to best trick the typechecker into
finding the BB(3) champion by itself.
</p>
<p>
<b>Extending OCaml's pattern matching – Yanni Lefki</b>
</p>
<p>
Pattern matching has been studied for decades and has been the subject of e=
xtensive research and numerous extensions. Nevertheless, recent language fe=
atures=E2=80=94such as Rust=E2=80=99s if-let construct, and recent work suc=
h as Cheng and Parreaux (OOPSLA 2024), suggest that there is still room for=
improvement. We propose a streamlined approach that unifies pattern matchi=
ng with extended forms of conditionals.
</p>
<p>
In particular, our prototype introduces binding-boolean-expressions, which =
allow variables to be bound within pattern guards, within if-conditions (an=
d subsequently used in the then branch), and within while-conditions (and u=
sed in the loop body). Our system also incorporates Haskell-style views, en=
abling the definition of smart deconstructors, the dual of smart constructo=
rs.
</p>
<p>
In this talk, we present an ML-like language equipped with evaluation rules=
, typing rules, and a simple compilation scheme. We conclude with a demonst=
ration of our implementation: an OCaml PPX prototype that parses an extende=
d ML syntax exposing these constructs, type-checks programs according to ou=
r (highly intuitive!) rules, and translates them into a correct OCaml AST v=
ia our (non-optimizing) transformation.
</p>
<p>
—
</p>
<p>
After the talks there will be some pizzas offered by the <a href=3D"https:/=
/ocaml-sf.org">OCaml Software Foundation</a> and later on we=E2=80=99ll mov=
e to a pub nearby as usual.
</p>
</div>
</div>
</div>
<div id=3D"outline-container-8" class=3D"outline-2">
<h2 id=3D"8">Stk 0.6 released</h2>
<div class=3D"outline-text-2" id=3D"text-8">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-stk-0-6-released/17994/=
1">https://discuss.ocaml.org/t/ann-stk-0-6-released/17994/1</a>
</p>
</div>
<div id=3D"outline-container-orgd87bc95" class=3D"outline-3">
<h3 id=3D"orgd87bc95">Zoggy announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgd87bc95">
<p>
Hello,
</p>
<p>
Stk is a SDL-based graphical user interface toolkit. Its interface is inspi=
red by Gtk and should look familiar to developers using Lablgtk.
</p>
<p>
Stk 0.6 is available. Among changes listed <a href=3D"https://zoggy.frama.i=
o/ocaml-stk/posts/release-0.6.0.html">here</a>, this release introduces <a =
href=3D"https://zoggy.frama.io/ocaml-stk/refdoc/stk/Stk/Tooltip/index.html"=
>Tooltips</a> and <a href=3D"https://zoggy.frama.io/ocaml-stk/doc-config.ht=
ml">handling of user's configuration</a>, including user-defined themes.
</p>
<p>
The <code>stk*</code> packages are available from my <a href=3D"https://fra=
magit.org/zoggy/opam-repository">personal opam repository</a>.
</p>
</div>
</div>
</div>
<div id=3D"outline-container-9" class=3D"outline-2">
<h2 id=3D"9">opam 2.5.1</h2>
<div class=3D"outline-text-2" id=3D"text-9">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-opam-2-5-1/17997/1">htt=
ps://discuss.ocaml.org/t/ann-opam-2-5-1/17997/1</a>
</p>
</div>
<div id=3D"outline-container-org51f738a" class=3D"outline-3">
<h3 id=3D"org51f738a">Kate announced</h3>
<div class=3D"outline-text-3" id=3D"text-org51f738a">
<p>
Hi everyone,
</p>
<p>
opam 2.5.1 is now available. This release is fixing a security issue (<a hr=
ef=3D"https://github.com/ocaml/security-advisories/blob/main/advisories/202=
6/OSEC-2026-03.md">OSEC-2026-03</a>) and other minor things. <i>Thanks to <=
a href=3D"https://github.com/andrew">@andrew</a> for reporting this issue.<=
/i>
</p>
<p>
We invite everyone to upgrade to 2.5.1 as soon as possible.
</p>
<p>
If you depend on the older opam package of your preferred distribution, dis=
tributions such as Debian Stable have already started backporting the relev=
ant fix and the patched version should be available there very soon.
</p>
<p>
You can read our <a href=3D"https://opam.ocaml.org/blog/opam-2-5-1/">blog p=
ost</a> for relevant links and details.
</p>
</div>
<div id=3D"outline-container-org36762fe" class=3D"outline-4">
<h4 id=3D"org36762fe">Try it!</h4>
<div class=3D"outline-text-4" id=3D"text-org36762fe">
<p>
The upgrade instructions are unchanged:
</p>
<p>
For Unix systems
</p>
<blockquote>
<p>
bash -c "sh <(curl -fsSL <a href=3D"https://opam.ocaml.org/install.sh">h=
ttps://opam.ocaml.org/install.sh</a>) –version 2.5.1"
</p>
</blockquote>
<p>
or from PowerShell for Windows systems
</p>
<blockquote>
<p>
Invoke-Expression "& { $(Invoke-RestMethod <a href=3D"https://opam.ocam=
l.org/install.ps1">https://opam.ocaml.org/install.ps1</a>) } -Version 2.5.1"
</p>
</blockquote>
<p>
Please report any issues to the <a href=3D"https://github.com/ocaml/opam/is=
sues">bug-tracker</a>.
</p>
<p>
Happy hacking,
</p>
<p>
<> <> The opam team <> <> :camel:
</p>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-10" class=3D"outline-2">
<h2 id=3D"10">Restarting OCaml.jp: The OCaml Japan User Group</h2>
<div class=3D"outline-text-2" id=3D"text-10">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-restarting-ocaml-jp-the=
-ocaml-japan-user-group/17998/1">https://discuss.ocaml.org/t/ann-restarting=
-ocaml-jp-the-ocaml-japan-user-group/17998/1</a>
</p>
</div>
<div id=3D"outline-container-org48e4337" class=3D"outline-3">
<h3 id=3D"org48e4337">mt_caret announced</h3>
<div class=3D"outline-text-3" id=3D"text-org48e4337">
<p>
Dear OCaml community,
</p>
<p>
We're excited to announce the relaunch of <b>OCaml.jp</b> (<a href=3D"https=
://ocaml.jp/">https://ocaml.jp/</a>), the OCaml Japan User Group!
</p>
<p>
Our goal is to grow and energize the OCaml community in Japan by bringing t=
ogether users to foster broader adoption and deeper engagement with OCaml a=
cross the country.
</p>
</div>
<div id=3D"outline-container-org4741324" class=3D"outline-4">
<h4 id=3D"org4741324">Current Activities</h4>
<div class=3D"outline-text-4" id=3D"text-org4741324">
<p>
We've already kicked off a couple of initiatives:
</p>
<ul class=3D"org-ul">
<li><b>OCaml Weekly News - Japanese Edition</b>: We're maintaining a Japane=
se translation of the OCaml Weekly News at <a href=3D"https://ocaml.jp/cwn-=
ja/">https://ocaml.jp/cwn-ja/</a>, making it easier for Japanese speakers t=
o stay up to date with the latest happenings in the OCaml ecosystem.</li>
<li><b>OCaml Meetup in Tokyo (August 2026)</b>: We are currently preparing =
to host an OCaml Meetup in Tokyo this August, the first one in <a href=3D"h=
ttps://ocaml.jp/events/">over ten years</a>! More details will be shared so=
on; please stay tuned!</li>
</ul>
</div>
</div>
<div id=3D"outline-container-orgfdf016b" class=3D"outline-4">
<h4 id=3D"orgfdf016b">Join Us!</h4>
<div class=3D"outline-text-4" id=3D"text-orgfdf016b">
<p>
We're using <b>Discord</b> as our primary communication platforms. Whether =
you're based in Japan, are a Japanese-speaking OCaml enthusiast anywhere in=
the world, or simply want to connect with the Japanese OCaml community, we=
'd love to have you join us!
</p>
<p>
Please use the following link to join Discord: <a href=3D"https://discord.g=
g/qQTbny8KF4">https://discord.gg/qQTbny8KF4</a>
</p>
<p>
We look forward to building a vibrant OCaml community in Japan together. =
=E3=82=88=E3=82=8D=E3=81=97=E3=81=8F=E3=81=8A=E9=A1=98=E3=81=84=E3=81=97=E3=
=81=BE=E3=81=99=EF=BC=81
</p>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-11" class=3D"outline-2">
<h2 id=3D"11">Code navigation and search on Github</h2>
<div class=3D"outline-text-2" id=3D"text-11">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-code-navigation-and-sea=
rch-on-github/17999/1">https://discuss.ocaml.org/t/ann-code-navigation-and-=
search-on-github/17999/1</a>
</p>
</div>
<div id=3D"outline-container-org1f90d90" class=3D"outline-3">
<h3 id=3D"org1f90d90">Pieter Goetschalckx announced</h3>
<div class=3D"outline-text-3" id=3D"text-org1f90d90">
<p>
GitHub is now using <a href=3D"https://github.com/tree-sitter/tree-sitter-o=
caml">tree-sitter-ocaml</a> for <a href=3D"https://docs.github.com/en/repos=
itories/working-with-files/using-files/navigating-code-on-github">code navi=
gation</a> and <a href=3D"https://docs.github.com/en/search-github/github-c=
ode-search/understanding-github-code-search-syntax#symbol-qualifier">code s=
earch</a>.
</p>
<ul class=3D"org-ul">
<li>Code highlighting should be more accurate (compared to the old TextMate=
grammar) and supports all features up to OCaml 5.4.</li>
<li>There is a symbols side panel for each file.</li>
<li>You can click on symbols to find definitions and references.</li>
<li>You can <a href=3D"https://github.com/search?q=3Drepo%3Aocaml%2Focaml+d=
ef%3Afind&type=3Dcode">search for definitions</a>.</li>
<li>There is limited support for <a href=3D"https://github.com/search?q=3Dr=
epo%3Aocaml%2Focaml+Make.t&type=3Dcode">nested structures</a>.</li>
</ul>
<p>
They enabled it <a href=3D"https://github.com/github/code-navigation/issues=
/14">a few months ago</a> already, but I forgot to post it here.
</p>
<p>
The code navigation is not always 100% accurate, but good enough to be help=
ful. If you encounter any issues with incorrectly highlighted code, this co=
uld be a tree-sitter-ocaml issue.
</p>
</div>
</div>
</div>
<div id=3D"outline-container-12" class=3D"outline-2">
<h2 id=3D"12">Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/=
2 libraries</h2>
<div class=3D"outline-text-2" id=3D"text-12">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/seeking-maintainers-for-our=
-ocaml-sip-server-grpc-and-http-2-libraries/18000/1">https://discuss.ocaml.=
org/t/seeking-maintainers-for-our-ocaml-sip-server-grpc-and-http-2-librarie=
s/18000/1</a>
</p>
</div>
<div id=3D"outline-container-orgde70a70" class=3D"outline-3">
<h3 id=3D"orgde70a70">Wojtek Czekalski announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgde70a70">
<p>
As we're moving off OCaml at <a href=3D"https://dialo.ai/">dialo</a>, we'd =
like to donate the libraries we built to people who will properly maintain =
them. We built a highly performant telephony system using OCaml, but as a s=
mall team we ended up maintaining too much software for our liking.
</p>
<p>
We initially built a SIP server implementation in OCaml, which was a perfec=
t fit. We needed to connect it to the rest of our system in a language agno=
stic way. We chose gRPC and that's where things got difficult.
</p>
<p>
At a smaller scale our own buggy implementation of gRPC on top of <a href=
=3D"https://github.com/anmonteiro/ocaml-h2">h2</a> was good enough. Then we=
started scaling and at the same time transitioned to OCaml 5.0. The combin=
ation of those factors resulted in:
</p>
<ol class=3D"org-ol">
<li>Performance regressions in 5.0 related to memory management, both insid=
e of app code, SIP stack, and inside of h2.</li>
<li>We needed a more robust implementation of gRPC to handle errors and edg=
e cases better.</li>
</ol>
<p>
Long story short we ended up:
</p>
<ol class=3D"org-ol">
<li>Writing our own implementation of <a href=3D"https://github.com/dialohq=
/haha">http2</a></li>
<li>Rewriting the gRPC library exclusively for eio to limit the scope toget=
her with <a href=3D"https://github.com/dialohq/ocaml-grpc/blob/dialo/exampl=
es/routeguide/src/client.ml">decent codegen</a> and robust</li>
</ol>
<p>
Then, in late 2025, we had to add new features to the SIP server and someth=
ing inside us just broke. The SIP server had accumulated quite a bit of leg=
acy code over 3.5 years, so we wanted to rewrite some parts. We were extrem=
ely excited to build the new architecture centered around effects — <=
a href=3D"https://discuss.ocaml.org/t/effect-composability-actual-callstack=
-vs-syntactic-scope/17536">only to discover that user-space effects and con=
currency libraries don't really work well together</a>, since callbacks los=
e their scope (duh). That was the final straw.
</p>
<p>
We decided to run two 1-week stints to try rewriting the service in Rust an=
d Go. We ended up choosing Rust. We still miss OCaml, but not having to imp=
lement and maintain our own http2/grpc/sip stack is a breath of fresh air.
</p>
<p>
So here we are — we're gradually removing OCaml from our stack, and t=
hat's why we'd like to donate:
</p>
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/dialohq/ocaml-grpc/tree/dialo">ocaml-grpc=
</a> - the new code is on <code>dialo</code> branch, eio only at the moment=
, battle tested on production. It does have some bugs in it but few and it'=
s pretty solid.</li>
<li><a href=3D"https://github.com/dialohq/haha">haha (http2)</a> - overall =
good but could be better. We cancel fibers too often, it's a very low hangi=
ng fruit to make it much faster.</li>
<li>Our SIP stack — this is currently not open source, but we're happ=
y to share the source code with the right person or team.</li>
</ul>
<p>
Please write dms to me and feel free to ask me or @adamchol about specifics.
</p>
</div>
</div>
</div>
<div id=3D"outline-container-13" class=3D"outline-2">
<h2 id=3D"13">ppx_mixins: slightly more elegant mixin syntax</h2>
<div class=3D"outline-text-2" id=3D"text-13">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-ppx-mixins-slightly-mor=
e-elegant-mixin-syntax/18001/1">https://discuss.ocaml.org/t/ann-ppx-mixins-=
slightly-more-elegant-mixin-syntax/18001/1</a>
</p>
</div>
<div id=3D"outline-container-orgd8003c6" class=3D"outline-3">
<h3 id=3D"orgd8003c6">Sacha Ayoun announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgd8003c6">
<p>
Hello,
</p>
<p>
I've written a tiny ppx called <a href=3D"https://github.com/soteria-tools/=
ppx_mixins"><code>ppx_mixins</code></a> so that one can write:
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-ocaml"><code><span style=3D"color: #242521; font-weig=
ht: bold;">type</span> <span style=3D"color: #444fcf; font-weight: bold;">u=
</span> <span style=3D"color: #a7601f;">[@@mixins Map.OrderedType + Printab=
le]</span>
</code></pre>
</div>
<p>
which gets desugared to
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-ocaml"><code><span style=3D"color: #242521; font-weig=
ht: bold;">type</span> <span style=3D"color: #444fcf; font-weight: bold;">u=
</span>
<span style=3D"color: #242521; font-weight: bold;">include</span> <span sty=
le=3D"color: #557400; font-weight: bold;">Map.OrderedType</span> <span styl=
e=3D"color: #242521; font-weight: bold;">with type</span> <span style=3D"co=
lor: #444fcf; font-weight: bold;">t</span> :=3D u
<span style=3D"color: #242521; font-weight: bold;">include</span> <span sty=
le=3D"color: #557400; font-weight: bold;">Printable</span> <span style=3D"c=
olor: #242521; font-weight: bold;">with type</span> <span style=3D"color: #=
444fcf; font-weight: bold;">t</span> :=3D u
</code></pre>
</div>
<p>
Not much but increases readability in a codebase that uses the "mixin" patt=
ern a lot
</p>
</div>
<div id=3D"outline-container-orgefab853" class=3D"outline-4">
<h4 id=3D"orgefab853">Constructing type signatures</h4>
<div class=3D"outline-text-4" id=3D"text-orgefab853">
<p>
In the upcoming release, one can also write
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-ocaml"><code><span style=3D"color: #242521; font-weig=
ht: bold;">module type</span> <span style=3D"color: #557400; font-weight: b=
old;">M</span> =3D <span style=3D"color: #a7601f; background-color: #ebebeb=
;">[%mixins</span> <span style=3D"color: #557400; font-weight: bold;">Map.<=
/span><span style=3D"color: #242521;">OrderedType</span> + <span style=3D"c=
olor: #242521;">Printable</span><span style=3D"color: #a7601f; background-c=
olor: #ebebeb;">]</span>
<span style=3D"color: #8f6f4a; font-style: italic;">(* </span><span style=
=3D"color: #8f6f4a; font-style: italic;">desugars to</span><span style=3D"c=
olor: #8f6f4a; font-style: italic;"> *)</span>
<span style=3D"color: #242521; font-weight: bold;">module type</span> <span=
style=3D"color: #557400; font-weight: bold;">M</span> =3D <span style=3D"c=
olor: #242521; font-weight: bold;">sig</span>=20
<span style=3D"color: #242521; font-weight: bold;">type</span> <span sty=
le=3D"color: #444fcf; font-weight: bold;">t</span>=20
<span style=3D"color: #242521; font-weight: bold;">include</span> <span =
style=3D"color: #557400; font-weight: bold;">Map.OrderedType</span> <span s=
tyle=3D"color: #242521; font-weight: bold;">with type</span> <span style=3D=
"color: #444fcf; font-weight: bold;">t</span> :=3D t
<span style=3D"color: #242521; font-weight: bold;">include</span> <span =
style=3D"color: #557400; font-weight: bold;">Printable</span> <span style=
=3D"color: #242521; font-weight: bold;">with type</span> <span style=3D"col=
or: #444fcf; font-weight: bold;">t</span> :=3D t
<span style=3D"color: #242521; font-weight: bold;">end</span>
</code></pre>
</div>
</div>
</div>
<div id=3D"outline-container-orgf3b871d" class=3D"outline-4">
<h4 id=3D"orgf3b871d">Additional features</h4>
<div class=3D"outline-text-4" id=3D"text-orgf3b871d">
<p>
One can also override other types, e.g.
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-ocaml"><code><span style=3D"color: #242521; font-weig=
ht: bold;">type</span> <span style=3D"color: #444fcf; font-weight: bold;">u=
</span> <span style=3D"color: #a7601f;">[@@mixins Mappable(key =3D int; val=
ue :=3D v)]</span>
<span style=3D"color: #8f6f4a; font-style: italic;">(* </span><span style=
=3D"color: #8f6f4a; font-style: italic;">desugars to</span><span style=3D"c=
olor: #8f6f4a; font-style: italic;"> *)</span>
<span style=3D"color: #242521; font-weight: bold;">type</span> <span style=
=3D"color: #444fcf; font-weight: bold;">u</span>
<span style=3D"color: #242521; font-weight: bold;">include</span> <span sty=
le=3D"color: #557400; font-weight: bold;">Mappable</span> <span style=3D"co=
lor: #242521; font-weight: bold;">with type</span> <span style=3D"color: #4=
44fcf; font-weight: bold;">t</span> :=3D u <span style=3D"color: #242521; f=
ont-weight: bold;">and type</span> <span style=3D"color: #444fcf; font-weig=
ht: bold;">key</span> =3D int <span style=3D"color: #242521; font-weight: b=
old;">and type</span> <span style=3D"color: #444fcf; font-weight: bold;">va=
lue</span> :=3D v
</code></pre>
</div>
</div>
</div>
<div id=3D"outline-container-org93bb1bf" class=3D"outline-4">
<h4 id=3D"org93bb1bf">Limitations</h4>
<div class=3D"outline-text-4" id=3D"text-org93bb1bf">
<ul class=3D"org-ul">
<li>No support for parametric types, e.g. <code>with type 'a u =3D 'a v</co=
de></li>
<li>No support for tuple and function types, e.g. <code>with type t =3D int=
-> bool</code></li>
</ul>
<p>
This is because the preprocessor parses the payload as an expression, and t=
hese don't parse nicely a expressions.
Deeper support (e.g. for mixins with type parameters) would probably also r=
equire language support.
</p>
</div>
</div>
</div>
</div>
<div id=3D"outline-container-14" class=3D"outline-2">
<h2 id=3D"14">Experience Report: Refining Dune=E2=80=99s Dependency Graph</=
h2>
<div class=3D"outline-text-2" id=3D"text-14">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/experience-report-refining-=
dune-s-dependency-graph/18002/1">https://discuss.ocaml.org/t/experience-rep=
ort-refining-dune-s-dependency-graph/18002/1</a>
</p>
</div>
<div id=3D"outline-container-orga755867" class=3D"outline-3">
<h3 id=3D"orga755867">Robin Bate Boerop announced</h3>
<div class=3D"outline-text-3" id=3D"text-orga755867">
<p>
<b>Refining Dune's Dependency Graph: Per-Module Library Filtering</b>
</p>
<p>
I've been working on improving Dune's inter-library dependency tracking, an=
d wanted to share the experience — both the technical details and wha=
t it's like as a first-time contributor to this large open source OCaml pro=
ject.
</p>
</div>
<div id=3D"outline-container-org233a853" class=3D"outline-4">
<h4 id=3D"org233a853">The Problem I Took On</h4>
<div class=3D"outline-text-4" id=3D"text-org233a853">
<p>
When <code>libA</code> depends on <code>libB</code>, Dune gives every modul=
e in <code>libA</code> a glob dependency on <i>all</i> <code>.cmi</code> fi=
les in <code>libB</code>. If any <code>.cmi</code> in <code>libB</code> cha=
nges, every module in <code>libA</code> is recompiled — even modules =
that never reference <code>libB</code>.
</p>
<p>
For projects with many libraries, this creates a cascade of unnecessary rec=
ompilations. The issue that tracks this matter <a href=3D"https://github.co=
m/ocaml/dune/issues/4572">#4572</a> has been open since 2021.
</p>
</div>
</div>
<div id=3D"outline-container-org51ab452" class=3D"outline-4">
<h4 id=3D"org51ab452">My Approach</h4>
<div class=3D"outline-text-4" id=3D"text-org51ab452">
<p>
Dune already runs <code>ocamldep</code> to compute intra-library module dep=
endencies. The key insight: that same output tells us which <i>libraries</i=
> each module references, via their entry module names. We can use this to =
filter both the build dependencies and the <code>-I~/</code>-H~ compiler fl=
ags per-module.
</p>
<p>
The implementation (<a href=3D"https://github.com/ocaml/dune/pull/14116">PR=
#14116</a> and <a href=3D"https://github.com/ocaml/dune/pull/14186">PR #14=
186</a>) works as follows:
</p>
<ol class=3D"org-ol">
<li>For each module and its transitive intra-library dependencies, read the=
<code>ocamldep</code> output (both <code>.ml</code> and <code>.mli</code>)=
</li>
<li>Union all referenced module names, including <code>-open</code> flags</=
li>
<li>Map those names to libraries via a <code>Lib_index</code></li>
<li>Transitively close the filtered library set via <code>Lib.closure</code=
></li>
<li>Use the result for both hidden deps and <code>-I~/</code>-H~ compiler f=
lags, partitioning into direct (visible via <code>-I</code>) and hidden (vi=
a <code>-H</code>) based on <code>requires_compile</code> membership</li>
</ol>
<p>
With both deps and flags filtered, a clean build will fail if a module refe=
rences a library it doesn't declare — previously, overly-broad <code>=
-I</code> flags could mask such errors.
</p>
</div>
</div>
<div id=3D"outline-container-org9587045" class=3D"outline-4">
<h4 id=3D"org9587045">A False Start</h4>
<div class=3D"outline-text-4" id=3D"text-org9587045">
<p>
My first attempt (<a href=3D"https://github.com/ocaml/dune/pull/14021">PR #=
14021</a>) tried to implement the filtering in a single PR without sufficie=
nt test coverage. It was closed after review revealed that the approach was=
fragile in edge cases I hadn't anticipated — particularly around tra=
nsparent module aliases and virtual libraries.
</p>
</div>
</div>
<div id=3D"outline-container-org357c2ff" class=3D"outline-4">
<h4 id=3D"org357c2ff">Challenges</h4>
<div class=3D"outline-text-4" id=3D"text-org357c2ff">
<p>
<b>Transparent module aliases.</b> OCaml's module alias mechanism means <co=
de>ocamldep</code> doesn't always report all libraries a module transitivel=
y depends on. If <code>libB</code> has <code>module M =3D LibC.Something</c=
ode>, and a module in <code>libA</code> uses <code>LibB.M</code>, <code>oca=
mldep</code> reports <code>LibB</code> but not <code>LibC</code>. The fix: =
transitively close the filtered library set using <code>Lib.closure</code>,=
bounded by the compilation context.
</p>
<p>
<b>Root modules.</b> The <code>(root_module)</code> stanza creates a module=
that implicitly aliases all libraries in the compilation context. When <co=
de>ocamldep</code> reports a reference to a root module, we can't determine=
which underlying libraries are actually needed, so we fall back to the ful=
l dependency set.
</p>
<p>
<b>Virtual libraries.</b> When virtual library implementations are present =
in the compilation context, parameter libraries may not appear in <code>req=
uires_compile</code>, so filtering could miss them. Another fallback case.
</p>
<p>
<b>Menhir-generated modules.</b> These mock modules aren't in the <code>oca=
mldep</code> dependency graph, so we skip filtering for them.
</p>
<p>
<b>Null build overhead.</b> The filtering reads <code>.d</code> files and c=
omputes library closures per-module. On a fresh <code>dune</code> process (=
no memo cache), this is new work on every build — including null buil=
ds where nothing changed. This is a real trade-off: better incremental rebu=
ild performance at the cost of some null-build overhead.
</p>
</div>
</div>
<div id=3D"outline-container-org42d2331" class=3D"outline-4">
<h4 id=3D"org42d2331">Prerequisite Test PRs</h4>
<div class=3D"outline-text-4" id=3D"text-org42d2331">
<p>
Before the implementation PRs, I submitted six test-only PRs to document ex=
isting behavior and establish a safety net:
</p>
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/ocaml/dune/pull/14017">#14017</a> —=
Baseline tests documenting current inter-library recompilation behavior</l=
i>
<li><a href=3D"https://github.com/ocaml/dune/pull/14031">#14031</a> —=
Test documenting module name shadowing between stanzas and libraries</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14100">#14100</a> —=
Test verifying library file deps in compilation rules and sandboxed builds=
</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14101">#14101</a> —=
Test verifying transparent alias incremental build safety</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14129">#14129</a> —=
Test verifying incremental builds with alias re-exported libraries</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14178">#14178</a> —=
Test documenting <code>ocamldep</code> behavior with transparent alias cha=
ins</li>
</ul>
<p>
This made the implementation PRs' diffs focused on the actual change, and g=
ave reviewers confidence that existing behavior was preserved. It also help=
ed me understand the edge cases that tripped up my first attempt.
</p>
</div>
</div>
<div id=3D"outline-container-orgc0850de" class=3D"outline-4">
<h4 id=3D"orgc0850de">The Review Process</h4>
<div class=3D"outline-text-4" id=3D"text-orgc0850de">
<p>
The Dune maintainers (<a href=3D"https://github.com/rgrinberg">@rgrinberg</=
a> and <a href=3D"https://github.com/art-w">@art-w</a>) provided thorough, =
constructive reviews. Some highlights:
</p>
<ul class=3D"org-ul">
<li>Replacing my hand-rolled transitive closure with <code>Lib.closure</cod=
e> from the existing library — a cleaner approach I wouldn't have fou=
nd without familiarity with Dune's internals</li>
<li>Identifying that both <code>.ml</code> and <code>.mli</code> ocamldep o=
utput need to be read, since the interface can reference different librarie=
s than the implementation</li>
<li>Suggesting per-module <code>-I~/</code>-H~ flag filtering, which makes =
clean builds more precise and improves caching</li>
<li>Questioning every fallback case and special-cased module kind, leading =
to simpler code</li>
</ul>
<p>
The PRs went through significant refactoring during review — the fina=
l versions are substantially tighter than the initial submissions.
</p>
</div>
</div>
<div id=3D"outline-container-org20d6b43" class=3D"outline-4">
<h4 id=3D"org20d6b43">What Could Be Better</h4>
<div class=3D"outline-text-4" id=3D"text-org20d6b43">
<p>
Working on this was a positive experience overall, but a few things created=
friction:
</p>
<p>
<b>No way to benchmark before merging.</b> The null-build overhead question=
came up late in the process. I discovered through manual benchmarking that=
the change added \~70% to null build time — a significant regression=
. Dune's benchmark CI workflow runs only on pushes to main, not on PRs. Con=
tributor-accessible performance tooling would help catch regressions before=
they land.
</p>
<p>
<b>Review momentum vs. rebasing.</b> The test PRs merged quickly, but the i=
mplementation PR required multiple rounds of review over days. Between roun=
ds, main moves forward, requiring rebases that risk introducing conflicts. =
The contributor carries the burden of keeping branches fresh. This is compo=
unded when PRs depend on each other — every rebase of #14116 required=
rebasing #14186 as well. GitHub has no first-class support for PR stacks, =
so this is manual and error-prone. Of course, all GitHub-hosted repos suffe=
r from this.
</p>
<p>
<b>Flaky CI</b>. Many CI runs had errors that were not related to my code. =
It was often an upstream provider of an OCaml package that was unreachable =
or faulty (temporarily). These problems often resolved themselves, but caus=
ed day-long delays in the PR lifetimes. The problem stems from the setup co=
de that is run and re-run over and over in CI jobs.
</p>
</div>
</div>
<div id=3D"outline-container-org17cdb7e" class=3D"outline-4">
<h4 id=3D"org17cdb7e">Reflections</h4>
<div class=3D"outline-text-4" id=3D"text-org17cdb7e">
<p>
The Dune codebase is well-structured, with clear separation between the bui=
ld engine, rule generation, and scheduler. It is also of good quality, maki=
ng it feel like time spent on keeping the quality high is worthwhile.
</p>
<p>
I found the cram test infrastructure good for testing. Each test scenario i=
s a self-contained shell script with expected output, making it easy to doc=
ument and verify exact recompilation behavior. It inspires confidence in th=
e code.
</p>
<p>
The maintainers have been responsive and the review process, while slowed b=
y thoroughness, is collaborative and professional. Thank you, maintainers!
</p>
</div>
</div>
</div>
<div id=3D"outline-container-orge36abb3" class=3D"outline-3">
<h3 id=3D"orge36abb3">Steffen Smolka then replied</h3>
<div class=3D"outline-text-3" id=3D"text-orge36abb3">
<blockquote>
<p>
GitHub has no first-class support for PR stacks
</p>
</blockquote>
<p>
It does now: <a href=3D"https://github.github.com/gh-stack/">https://github=
.github.com/gh-stack/</a>
</p>
</div>
</div>
</div>
<div id=3D"outline-container-15" class=3D"outline-2">
<h2 id=3D"15">First beta release of OCaml 5.5.0</h2>
<div class=3D"outline-text-2" id=3D"text-15">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/first-beta-release-of-ocaml=
-5-5-0/18006/1">https://discuss.ocaml.org/t/first-beta-release-of-ocaml-5-5=
-0/18006/1</a>
</p>
</div>
<div id=3D"outline-container-orgec8631f" class=3D"outline-3">
<h3 id=3D"orgec8631f">octachron announced</h3>
<div class=3D"outline-text-3" id=3D"text-orgec8631f">
<p>
With most developer tools available and the good stability of the compiler,=
I am happy to announce the first beta release of OCaml 5.5.0.
</p>
<p>
Compared to the last alpha, this new version improves the manpage for
ocamlopt and fixes:
</p>
<ul class=3D"org-ul">
<li>two runtime bugs (for ephemerons and the bytecode interpreter)</li>
<li>two type system bugs (for classes and module-dependent functions)</li>
<li>three warning or error message bugs</li>
</ul>
<p>
(See the Changelog below for a full list).
</p>
<p>
Concerning the associated compiler tools, most of them are already
available (as least in a preview version), and there are patches in
progress for the remaining ones. You can track the last remaining
update efforts on the <a href=3D"https://github.com/ocaml/opam-repository/i=
ssues/29463">release readiness meta-issue</a>.
</p>
<p>
Thus, it should be safe to test your libraries and programs with the
new version OCaml 5.5.0 version in preparation of the final release.
If everything goes well, we might see a release in May.
</p>
<p>
If you find any bugs, please report them to the <a href=3D"https://github.c=
om/ocaml/ocaml/issues">GitHub issue tracker</a>.
</p>
<p>
If you are interested by the full list of new features and bug fixes, the
<a href=3D"https://github.com/ocaml/ocaml/blob/5.5/Changes">changelog for O=
Caml 5.5.0</a> is the most up-to-date resource.
</p>
<p>
Happy hacking,
Florian Angeletti for the OCaml team.
</p>
</div>
<div id=3D"outline-container-org4dcafbc" class=3D"outline-4">
<h4 id=3D"org4dcafbc">Installation Instructions</h4>
<div class=3D"outline-text-4" id=3D"text-org4dcafbc">
<p>
The base compiler can be installed as an opam switch with the following com=
mands
on opam 2.1 and later:
</p>
<pre class=3D"example" id=3D"org3c834e4">
opam update
opam switch create 5.5.0~beta1
</pre>
<p>
The source code for the beta is also available at these addresses:
</p>
<ul class=3D"org-ul">
<li>GitHub: <a href=3D"https://github.com/ocaml/ocaml/archive/5.5.0-beta1.t=
ar.gz">https://github.com/ocaml/ocaml/archive/5.5.0-beta1.tar.gz</a></li>
<li>OCaml archives at Inria: <a href=3D"https://caml.inria.fr/pub/distrib/o=
caml-5.5/ocaml-5.5.0~beta1.tar.gz">https://caml.inria.fr/pub/distrib/ocaml-=
5.5/ocaml-5.5.0~beta1.tar.gz</a></li>
</ul>
</div>
</div>
<div id=3D"outline-container-orgb8283a5" class=3D"outline-4">
<h4 id=3D"orgb8283a5">Fine-Tuned Compiler Configuration</h4>
<div class=3D"outline-text-4" id=3D"text-orgb8283a5">
<p>
If you want to tweak the configuration of the compiler, you can switch to t=
he option variant with:
</p>
<pre class=3D"example" id=3D"org6cba654">
opam update
opam switch create <switch_name> ocaml-variants.5.5.0~beta1+options &=
lt;option_list>
</pre>
<p>
where <code>option_list</code> is a space separated list of <code>ocaml-opt=
ion-*</code> packages. For instance, for a flambda and no-flat-float-array =
switch:
</p>
<pre class=3D"example" id=3D"orgbcbbb66">
opam switch create 5.5.0~beta1+flambda+nffa ocaml-variants.5.5.0~beta1+opti=
ons ocaml-option-flambda ocaml-option-no-flat-float-array
</pre>
<p>
All available options can be listed with <code>opam search ocaml-option</co=
de>.
</p>
</div>
</div>
<div id=3D"outline-container-orge781fe6" class=3D"outline-4">
<h4 id=3D"orge781fe6">Changes compared to the last alpha</h4>
<div class=3D"outline-text-4" id=3D"text-orge781fe6">
</div>
<ul class=3D"org-ul">
<li><a id=3D"org9504415"></a>Documentation update<br />
<div class=3D"outline-text-5" id=3D"text-org9504415">
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14684">#14684</a>: Imp=
rove ocamlopt's manual page
(Samuel Hym, review by Florian Angeletti)</li>
</ul>
</div>
</li>
<li><a id=3D"orga9fa308"></a>Runtime fixes<br />
<div class=3D"outline-text-5" id=3D"text-orga9fa308">
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14644">#14644</a>, <a =
href=3D"https://github.com/ocaml/ocaml/issues/14647">#14647</a>: Fix a bug =
related to unhandled effects in bytecode.
(Vincent Laviron, report by Thibaut Mattio,
review by Nicol=C3=A1s Ojeda B=C3=A4r, Stephen Dolan and Olivier Nicole)</=
li>
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14349">#14349</a>, <a =
href=3D"https://github.com/ocaml/ocaml/issues/14718">#14718</a>: runtime, f=
ix in the orphaning of ephemerons
(Gabriel Scherer, review by Olivier Nicole and Damien Doligez,
report by Jan Midtgaard)</li>
</ul>
</div>
</li>
<li><a id=3D"org240ce72"></a>Type system fixes<br />
<div class=3D"outline-text-5" id=3D"text-org240ce72">
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14557">#14557</a>, <a =
href=3D"https://github.com/ocaml/ocaml/issues/12150">#12150</a>, <a href=3D=
"https://github.com/ocaml/ocaml/issues/14696">#14696</a>: ensure that the s=
elf type of class cannot escape
through type constraints.
(Leo White, review by Florian Angeletti)</li>
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14667">#14667</a>: ena=
ble application related warnings for module-dependent functions
(Florian Angeletti, review by Gabriel Scherer)</li>
</ul>
</div>
</li>
<li><a id=3D"org424c420"></a>Error messages and warning fixes<br />
<div class=3D"outline-text-5" id=3D"text-org424c420">
<ul class=3D"org-ul">
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14690">#14690</a>: Fix=
<code>Name_type_mismatch</code> error message when the expected type is an
alias: print the expanded path on the right-hand side of the equality, not
the alias twice.
(Weixie Cui, review by Florian Angeletti)</li>
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14719">#14719</a>, <a =
href=3D"https://github.com/ocaml/ocaml/issues/14721">#14721</a>: compute ar=
ity correctly for module-dependent function
(Florian Angeletti, report by Jeremy Yallop, review by Stefan Muenzel)</li>
<li><a href=3D"https://github.com/ocaml/ocaml/issues/14655">#14655</a>, <a =
href=3D"https://github.com/ocaml/ocaml/issues/14691">#14691</a>: check for =
size overflow in caml_ba_reshape
(Stephen Dolan, review by Xavier Leroy)</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
<div id=3D"outline-container-16" class=3D"outline-2">
<h2 id=3D"16">ocgtk 0.1: OCaml bindings for GTK 4 (preview release)</h2>
<div class=3D"outline-text-2" id=3D"text-16">
<p>
Archive: <a href=3D"https://discuss.ocaml.org/t/ann-ocgtk-0-1-ocaml-binding=
s-for-gtk-4-preview-release/17944/5">https://discuss.ocaml.org/t/ann-ocgtk-=
0-1-ocaml-bindings-for-gtk-4-preview-release/17944/5</a>
</p>
</div>
<div id=3D"outline-container-org482baf0" class=3D"outline-3">
<h3 id=3D"org482baf0">Continuing this thread, Chris Armstrong announced</h3>
<div class=3D"outline-text-3" id=3D"text-org482baf0">
<p>
<i>ocgtk preview1 release has landed in opam.</i>
</p>
<p>
(preview0 was abandoned as considerable work was required to get it buildin=
g on other Linux distributions and Mac). A special thanks to @jmid for help=
ing me get it over the line.
</p>
<p>
In addition to the features above, it includes:
</p>
<ul class=3D"org-ul">
<li>Extended support for more GLib types, including integer primitives (gui=
nt8, int16, guint32, etc) and lists (GLib.SList and GLib.List)</li>
<li>Gobject interfaces</li>
</ul>
<p>
The combination of the above enables more methods to be generated (that wer=
e previously excluded) when they include those types in their parameters an=
d/or return types, opening up much more of the API surface of GTK (and rel=
ated libraries).
</p>
<p>
<b>Next steps</b>: my focus now is on internal cleanup and reorganisation t=
o better structure the tests and split gir_gen (the GObject code generator)=
into a seperate dune project. This will reduce the dependency list conside=
rably and enable targeting earlier OCaml versions, as well as reducing rele=
ase headaches related to gir_gen (which is not required by packages just us=
ing ocgtk)
</p>
</div>
</div>
</div>
<div id=3D"outline-container-orgc3cc6cf" class=3D"outline-2">
<h2 id=3D"orgc3cc6cf">Old CWN</h2>
<div class=3D"outline-text-2" id=3D"text-orgc3cc6cf">
<p>
If you happen to miss a CWN, you can <a href=3D"mailto:alan.schmitt@polytec=
hnique.org">send me a message</a> and I'll mail it to you, or go take a loo=
k at <a href=3D"https://alan.petitepomme.net/cwn/">the archive</a> or the <=
a href=3D"https://alan.petitepomme.net/cwn/cwn.rss">RSS feed of the archive=
s</a>.
</p>
<p>
If you also wish to receive it every week by mail, you may subscribe to the=
<a href=3D"https://sympa.inria.fr/sympa/info/caml-list">caml-list</a>.
</p>
<div class=3D"authorname" id=3D"org6025f46">
<p>
<a href=3D"https://alan.petitepomme.net/">Alan Schmitt</a>
</p>
</div>
</div>
</div>
</div>
</body>
</html>
--==-=-=--
--=-=-=--
--===-=-=
Content-Type: application/pgp-signature; name="signature.asc"
-----BEGIN PGP SIGNATURE-----
iQFvBAEBCABZFiEE6lXof/BsSVW56ZmGBA0KO07S5ccFAmnnRJ0bFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMCwzHxxhbGFuLnNjaG1pdHRAcG9seXRlY2huaXF1ZS5v
cmcACgkQBA0KO07S5ceTXggAzTQNhx7nmxq8aUT1xY5MQIbgU48FeoBPoZwxLzLB
K7Y4VPaNOaAZCH8zFVpErg2m2rBdNE86OEQ6bcBFoDz2E5F9HJiKCmXFt9d0ergD
vLM0KJueY8r0DBGv6WlQ//DiQghMxzRPil8x8TVwWKHJQ2qTGsruolRP8FgHirrI
jht4Pwu//TBbyzrMqiXEXrRjG6abNuVOwnoe/TdXYYA1Sp8SOS6r921vDOTy51Xh
ctJlJvPHPDjW2QArY8+krd6ETmiZP3sv685y7NtLtBqG99blUge9vb9hvvCGcq2s
47ddRAjeNiwLSUhvSon35uFLdKoC47phYV1VDm0ttbd19w==
=Wn1s
-----END PGP SIGNATURE-----
--===-=-=--