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 &amp; 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>
&mdash;
</p>

<p>
This time we=E2=80=99ll have the following talks:
</p>

<p>
<b>When Turing machines meet GADTs &ndash; 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 &ndash; 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>
&mdash;
</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 &lt;(curl -fsSL <a href=3D"https://opam.ocaml.org/install.sh">h=
ttps://opam.ocaml.org/install.sh</a>) &ndash;version 2.5.1"
</p>
</blockquote>
<p>
or from PowerShell for Windows systems
</p>
<blockquote>
<p>
Invoke-Expression "&amp; { $(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>
&lt;&gt; &lt;&gt; The opam team &lt;&gt; &lt;&gt; :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&amp;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&amp;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 &mdash; <=
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 &mdash; 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 &mdash; 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=
 -&gt; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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> &mdash;=
 Baseline tests documenting current inter-library recompilation behavior</l=
i>
<li><a href=3D"https://github.com/ocaml/dune/pull/14031">#14031</a> &mdash;=
 Test documenting module name shadowing between stanzas and libraries</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14100">#14100</a> &mdash;=
 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> &mdash;=
 Test verifying transparent alias incremental build safety</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14129">#14129</a> &mdash;=
 Test verifying incremental builds with alias re-exported libraries</li>
<li><a href=3D"https://github.com/ocaml/dune/pull/14178">#14178</a> &mdash;=
 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &lt;switch_name&gt; ocaml-variants.5.5.0~beta1+options &=
lt;option_list&gt;
</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-----
--===-=-=--