From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Authentication-Results: plum.tunbury.org; dkim=pass (1024-bit key; unprotected) header.d=inria.fr header.i=@inria.fr header.a=rsa-sha256 header.s=dc header.b=uwvt4nvz; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.134.164.83; helo=mail2-relais-roc.national.inria.fr; envelope-from=caml-list-owner@inria.fr; receiver=tunbury.org Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by plum.tunbury.org (Postfix) with ESMTP id 1D2EE4009B for ; Tue, 21 Apr 2026 09:34:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=inria.fr; s=dc; h=from:to:date:message-id:mime-version:subject:reply-to: sender:list-id:list-help:list-subscribe:list-unsubscribe: list-post:list-owner:list-archive; bh=C9DZnmaUKvXdvmNSn44IUbS9UYFjBylqTe7dgodU8n4=; b=uwvt4nvzRXUm1hE7BpkJrBMIAX5QicdfPxT9SSALftZ1WrFEzdr7IdUM 4JmOOBhlyklw8o7m0rAXz5Ty/P2r0JFLPS5ABloI0gysnGaNWVUraqwqN 8Ot/YNHNcljCa0LYg9VXBRaKS16agTB7Oe5AJRfQMKr6DZ7LCAY6ofFGQ k=; X-CSE-ConnectionGUID: GT/Q+0hjSRCLE280ckPjBg== X-CSE-MsgGUID: 6dmmWfmLSVaLBvyJUtsyBA== Authentication-Results: mail2-relais-roc.national.inria.fr; dkim=none (message not signed) header.i=none; spf=SoftFail smtp.mailfrom=caml-list-owner@inria.fr; spf=None smtp.helo=postmaster@prod-sympa-app.inria.fr Received-SPF: SoftFail (mail2-relais-roc.national.inria.fr: domain of caml-list-owner@inria.fr is inclined to not designate 128.93.162.27 as permitted sender) identity=mailfrom; client-ip=128.93.162.27; receiver=mail2-relais-roc.national.inria.fr; envelope-from="caml-list-owner@inria.fr"; x-sender="caml-list-owner@inria.fr"; x-conformance=spf_only; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:128.93.142.0/24 ip4:192.134.164.0/24 ip4:128.93.162.160 ip4:128.93.162.3 ip4:128.93.162.88 ip4:89.107.174.7 mx ~all" Received-SPF: None (mail2-relais-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@prod-sympa-app.inria.fr) identity=helo; client-ip=128.93.162.27; receiver=mail2-relais-roc.national.inria.fr; envelope-from="caml-list-owner@inria.fr"; x-sender="postmaster@prod-sympa-app.inria.fr"; x-conformance=spf_only X-IronPort-AV: E=Sophos;i="6.23,191,1770591600"; d="asc'?scan'208,217";a="273438568" Received: from prod-sympa-app.inria.fr ([128.93.162.27]) by mail2-relais-roc.national.inria.fr with ESMTP; 21 Apr 2026 11:34:46 +0200 Received: by prod-sympa-app.inria.fr (Postfix, from userid 990) id 81C8B82FF3; Tue, 21 Apr 2026 11:34:46 +0200 (CEST) Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by prod-sympa-app.inria.fr (Postfix) with ESMTP id 87D1282FB4 for ; Tue, 21 Apr 2026 11:34:33 +0200 (CEST) X-CSE-ConnectionGUID: 6wOE3D/wR0qV+owdjgyfNQ== X-CSE-MsgGUID: LO+UjBB6TGeTEBq1XE25kQ== IronPort-SDR: 69e744a6_riMpKKWGWUUmYLWtNhcfKeAK8XCJpsWxcPShR6z10Bh/NSK Neh69Fcuxt2pfaPw2a4YAq7r/aWWabPANuFR4XQ== X-ThreatScanner-Verdict: Negative X-IPAS-Result: =?us-ascii?q?A0GFAAD8Q+dpjyIeaIFRCRYDAQEBAQEBAQEBAQEBAQEBA?= =?us-ascii?q?QEBEgEBAQEBAQEBAQEBAYIQgT1bKRoBbF8zBwhJA4RVgWOBbI4lgRaQN4p7D?= =?us-ascii?q?YFcgSwWIQIOBwEDAQgFLgEbBAECBAEBAQEBAQIBgguBPYE3Ao0tAh8GAQQ0E?= =?us-ascii?q?wECBAEBAQEDAgMBAQEBAQEBAQEBAQsBAQEEAQEBAgEBAgQDAQEBAQIQAQEBA?= =?us-ascii?q?QEBOQVJhhUBBjMNgkUtJFMNEWAEAQIGAQYBAQEBAQEBAQECAQEBIgEBAQEBA?= =?us-ascii?q?QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECBAcBAQc8P?= =?us-ascii?q?xwBCAQGEwEBJQcGBhgUDwMJCwEGAwIRATUDARMBDgQUBgGCZwGCIgJPAwUMB?= =?us-ascii?q?j+VNJsNN3p/M4EBO4FRAQEGgQg+AgECCQICAwEOCSUB2hGBXgkJFAGBOAGBV?= =?us-ascii?q?4QagkoPDQEFJUlqAgEChE8JhDYnD4FVRIEVNYFzSgdvgVCBEQEBAQEBF0I9C?= =?us-ascii?q?AEEBQEIAgEBBQIBBgISDxETCQmDHIJpghEVehQdgVsGLgaBNBKBB4FdBR0wL?= =?us-ascii?q?FQGYoVigkIsAVUTFwsHBV6BCAMqLy1uMh2BIz4XNFgbBwWBS4Q2gVeBC4Mxg?= =?us-ascii?q?TcDC209NxQbiRUQIQ2BHkMZIRCBLgkmDi8JBgEBDQEHBQ8TGwgBAhEHCQUFA?= =?us-ascii?q?QcDCQgOAQEUDAINHwEBBwEFHhYKFQQRCBEBCRYFAQEBDQIBCQEHBQYBCAILA?= =?us-ascii?q?gQYEQOEYI1jFBAUAQMdDQN0jmQBoS9fbTQHhB+BXgYMiQiBJpYHhASBV4VAh?= =?us-ascii?q?XyHApE2gRwimGQigjaHKIEmCQeBaB9MiHqMKhAsIBMGYoQ9gX8jSSM/AQEBG?= =?us-ascii?q?AECDAczGjBDDQKCJAEzCQoMMRwPhAaFMIRJIgwWgRMBBAVKgXgQWhc9IoEEI?= =?us-ascii?q?oFSO4FxvSdBNQIBAQoxBwIHAQsEhWsBAYwGAQEPFwQDBW5dAQE?= IronPort-PHdr: A9a23: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 o9VZM94v2bhFahEPpmIvnBwvabgmCaxxg== IronPort-Data: A9a23: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 IronPort-HdrOrdr: A9a23:Cm+HaaHY/uyQj+PIpLqE18eALOsnbusQ8zAXPiFKOH5om6mj/a 2TdZsgtCMc5Ax8ZJhCo6HiBEDjexPhHPdOiOF7AV7IZmfbUQWTQ71K3M/L/HnLGiH19OJRvJ 0QFpRWOZnXFlY/qc775WCDYrEdKTS8gcSVuds= X-Talos-CUID: 9a23:htlyemPo7iRcCu5DBjZA2RU4Xd8fKmTjj3DPL023GGhPcejA X-Talos-MUID: 9a23:9dAVawsk8PZ6UHXAgs2noBYhCcVCyfqSJ00xvL8f4vmpb3FzAmLI X-IronPort-Anti-Spam-Filtered: true X-URL-LookUp-ScanningError: 1 X-IronPort-AV: E=Sophos;i="6.23,191,1770591600"; d="asc'?scan'208,217";a="144664585" X-URL-ContentFilter: X-IronPort-Outbreak-Status: No, level 0, Unknown - Unknown X-MGA-submission: =?us-ascii?q?MDHhGPGUS4bxordpLJ21SNitUcr/61fUmHEs56?= =?us-ascii?q?r3pAld8n8gDmNBcFhMNWYBycZ5XXJLBMX4ipKtYgKJAA245XuUF5sOT8?= =?us-ascii?q?gtJSabbvjRKnyj9zzjIprpVdiS4QnTR6/7BHffaUMcWSy5cWIYH66DZc?= =?us-ascii?q?POltd3FkYmx9Wx3sLGW7x0Gw=3D=3D?= Received: from mx1.polytechnique.org ([129.104.30.34]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Apr 2026 11:34:30 +0200 Received: from mac-03220211.irisa.fr (mac-03220211.irisa.fr [131.254.21.249]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ssl.polytechnique.org (Postfix) with ESMTPSA id 774071A496; Tue, 21 Apr 2026 11:34:23 +0200 (CEST) From: Alan Schmitt To: "lwn" , caml-list@inria.fr Date: Tue, 21 Apr 2026 11:34:20 +0200 Message-ID: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="===-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-AV-Checked: ClamAV using ClamSMTP at svoboda.polytechnique.org (Tue Apr 21 11:34:25 2026 +0200 (CEST)) X-Spam-Flag: Unsure, tests=bogofilter, spamicity=0.484425, queueID=3115C1A49A X-Org-Mail: alan.schmitt.1995@polytechnique.org Subject: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News Reply-To: Alan Schmitt X-Loop: caml-list@inria.fr X-Sequence: 19493 Errors-To: caml-list-owner@inria.fr Precedence: list Precedence: bulk Sender: caml-list-request@inria.fr X-no-archive: yes List-Id: List-Help: , List-Subscribe: , List-Unsubscribe: , List-Post: List-Owner: List-Archive: Archived-At: --===-=-= 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: 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 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: 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] 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: 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] [different in spirit] 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: 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] [the full changelog] 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] [@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: 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 . You can subscribe to ptt@mailingl.st by sending an email to ptt-subscribe@mailingl.st 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] [Enron] [KVM] [caml-list] [Hamlet] [unstrctrd] [rosetta] [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] [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] [uspf] [ocaml-dmarc] [here] 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] [Miou] [Mkernel] [Mnet] [Mfat] [mkernel-memtrace] [memtrace-viewer] [mirage-tcpip] [mnet] [this tutorial] 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] [Mollymawk] [our cooperative] 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'] =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 (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] [bm25] [here] [blame] [vif] [bancos] [here] [carton] [ocaml-git] [public-inbox] 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: 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: [Albatross] [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: 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] [register on meetup ] [OUPS=E2=80=99 website ] [OCaml Zulip] [OCaml Software Foundation] 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: 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] [Tooltips] [handling of user's configuration] [personal 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: 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] [@andrew] [blog post] 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 ) =E2=80=93version 2.5.1" or from PowerShell for Windows systems Invoke-Expression "& { $(Invoke-RestMethod ) } -Version 2.5.1" Please report any issues to the [bug-tracker]. Happy hacking, <> <> The opam team <> <> :camel: [bug-tracker] 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: 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/] 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/] [over ten years] 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] 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: 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] [code navigation] [code search] [search for definitions] [nested structures] [a few months ago] 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: 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] [h2] [http2] [decent codegen] [only to discover that user-space effects and concurrency libraries don't really work well together] [ocaml-grpc] [haha (http2)] 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: 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'] 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: 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] 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] [PR #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] 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] [#14031] [#14100] [#14101] [#14129] [#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] [@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: 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: 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] [GitHub issue tracker] [changelog for OCaml 5.5.0] 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: =E2=80=A2 OCaml archives at Inria: 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 ocaml-variants.5.5.0~beta1+opt= ions =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] =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] [#14647] [#14349] [#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] [#12150] [#14696] [#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] [#14719] [#14721] [#14655] [#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: 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] [the archive] [RSS feed of the archives] [caml-list] [Alan Schmitt] --==-=-= Content-Type: text/html; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable OCaml Weekly News

OCaml Weekly News

Previous Week<= /a> Up Next Week

Hello

Here is the latest OCaml Weekly News, for the week of April 14 to 21, 2026.

http-date v0.2 =E2=80=94 Zero-dependency HTTP date parsing for= OCaml

Bikal Lem announced

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

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

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.

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

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.

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

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

https://github.com/bikall= em/http-date

Caqti 2.3.0

Petter A. Urkedal announced

I would like to announce the release of Caqti 2.3.0.

TL;DR: Consider adding the caqti.classic to your link line (av= ailable since this version). It currently only re-exports the caqti<= /code> library, but will be replaced by a compatibility layer for the Caqti= 2 API in Caqti 3 to allow incremental migration.

Release Notes

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 comp= atibility. Instead, users are encouraged to add the new caqti.classic to = their dependencies to ease migration to Caqti 3.

  • Added an alias caqti.classic for the caqti 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.
  • The dialect descriptor for MariaDB in caqti.template now p= rovides the server version.
  • Added Query.parens, Query.litf, Query.v= ars, Row_type.fields to the caqti.template library.
  • 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 Caqti_template.Constructor_type module.<= /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.
  • 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 i= s set. This should simplify debugging when the query is assembled from different parts of the application code.
  • The still unstable caqti.template library now supports mul= tiple statements in a single request template, sent opportunistically as a single query where allowed. This is still experimental.
  • Fixed package scoping of shim rules for sqlite3 (#133 by mefyl).
  • Fixed the error classification for the SQLite3 driver (#132).
  • Fixed reconnect after connection loss for PostgreSQL.

layoutz 0.1.0 =F0=9F=AA=B6 - Zero-dep Elm-style TUIs and termi= nal plots for your OCaml apps

Matthieu Court announced

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-ins.

Looking for feedback! Many thanks

Dune 3.22

Continuing this thread, Shon announced

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. T= hank you, contributors!

If you encounter a problem with this release, please report it in [our issue

Fixed

  • Revert the change in behavior of --diff-command back to 3.= 21. Non-existent files are now passed to this command instead of being repl= aced with /dev/null (#= 14098, fixes 13891, @rgrinberg= )

ptt, a mailing list system as unikernel

Calascibetta Romain announced

Hey! We just launched a new mailing list powered entirely by OCaml unikerne= ls. The website (itself a unikernel) is at = https://mailingl.st. You can subscribe to ptt@mailingl.st by sending an= email to ptt-subscribe@mailingl.st 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 t= he long run, it will focus on our ptt project.

The SMTP protocol: a long and winding road!

  • In the beginning, email

    It all started with Mr.MIME, 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, Enron, KVM 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.

    This work also let us build Ha= mlet, 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 constrai= nts and (Comment) Folding Whitespace handling.

  • Next, the protocol

    Then came colombe, our OC= aml implementation of the SMTP protocol. It uses ocaml-tls for STARTTLS support.

    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.

  • Finally, legitimacy

    On top of these core components, we built several email security layers:

    • ocaml-dkim handles= signing and verifying email integrity in a streaming fashion (both for ver= ification and signature generation)
    • uspf verifies sender ide= ntity and, like most of our libraries, stays independent of any scheduler o= r DNS implementation
    • ocaml-dmarc au= tomates DKIM and SPF verification, stamps emails with the result, and check= s alignment across a domain name
    • [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)

    We wrote a short article about all of this here.

All in the form of unikernels

Our first experiments already showed that we could handle emails with MirageOS unikernels. B= ut we also hit real limitations: memory leaks, security vulnerabilities, an= d build issues.

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:

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, viewa= ble via memtrace-viewer= ). The CVEs related to mirage-tcpip 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 mnet.

Other unikernels using this approach are available too. If you=E2=80=99re c= urious, check out this tutor= ial on creating a unikernel in OCaml.

Deployment

ptt also tackles the deployment question. We have an article present= ing the "stateless" aspect of ptt. We'd also like to (re)intro= duce [Albatross](github.com/robur-coop/albatross), our secure unikernel orc= hestrator, and Mollyma= wk, a web interface for deploying unikernels (which is itself a unikern= el).

More broadly, this is what our cooperative 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!

Usage

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 blaze came about: = a Swiss Army knife for handling emails.

It=E2=80=99s still experimental, but it already lets you:

  • use our archive system (generate, read, index, etc.)
  • handle other archives such as mbox or maildir=
  • communicate via the POP3 protocol
  • sign and verify emails (DKIM and ARC)
  • build emails from the command line
  • send emails
  • run a small local SMTP server

blaze 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.

  • Archiving & Indexing

    We'd also like to present the stem 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 bm25 search engine. You can s= ee results here.

    This is also what drives our caml-list search engine, available as a uniker= nel: blame, which you c= an try at https://caml-list.robur.= coop (powered by vif).

    Beyond search, there's also email indexing via Message-IDs. For that we bui= lt bancos: a persis= tent radix tree in OCaml that supports parallel access! More det= ails he= re.

    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 d= ecided to reuse it for archiving emails (much like public-inbox did, though in a different form).

Conclusion

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!

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!

Mollymawk and Albatross orchestrating all virtual machines

Hannes Mehnert announced

Dear everyone,

we just finished and deployed Albatross and Mollymawk to support virtual machines that are not MirageOS unikernel= s.

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.

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!

We also wrote a brief blog article with screenshots: https://blog.robur.coop/article= s/mollymawk-other.html

OUPS meetup april 2026

ancolie announced

The next OUPS meetup will take place on Wednesday, 29th of April 202= 6. It will start at 6:30pm at the 45 rue d'Ulm in Paris. It w= ill be in the in the Rataud amphitheater.

:warning: It's not in Jussieu as usual but in ENS Ulm! If you're not famili= ar with the place, there is a map of the buildings.

Please, register on meetup as soon as possible to let us know how many pi= zza 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 t= he OCaml Zulip. Feel free to co= ntact us there if you=E2=80=99d like to suggest talks.

This time we=E2=80=99ll have the following talks:

When Turing machines meet GADTs – 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 – Yanni Lefki

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.

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.

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.

After the talks there will be some pizzas offered by the OCaml Software Foundation and later on we=E2=80=99ll mov= e to a pub nearby as usual.

Stk 0.6 released

Zoggy announced

Hello,

Stk is a SDL-based graphical user interface toolkit. Its interface is inspi= red 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.

opam 2.5.1

Kate announced

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 <= a href=3D"https://github.com/andrew">@andrew for reporting this issue.<= /i>

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, dis= tributions such as Debian Stable have already started backporting the relev= ant fix and the patched version should be available there very soon.

You can read our blog p= ost for relevant links and details.

Try it!

The upgrade instructions are unchanged:

For Unix systems

bash -c "sh <(curl -fsSL h= ttps://opam.ocaml.org/install.sh) –version 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:

Restarting OCaml.jp: The OCaml Japan User Group

mt_caret announced

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 t= ogether users to foster broader adoption and deeper engagement with OCaml a= cross the country.

Current Activities

We've already kicked off a couple of initiatives:

  • OCaml Weekly News - Japanese Edition: We're maintaining a Japane= se translation of the OCaml Weekly News at https://ocaml.jp/cwn-ja/, making it easier for Japanese speakers t= o stay up to date with the latest happenings in the OCaml ecosystem.
  • OCaml Meetup in Tokyo (August 2026): We are currently preparing = to host an OCaml Meetup in Tokyo this August, the first one in over ten years! More details will be shared so= on; please stay tuned!

Join Us!

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

Code navigation and search on Github

Pieter Goetschalckx announced

GitHub is now using tree-sitter-ocaml for code navi= gation and code s= earch.

  • Code highlighting should be more accurate (compared to the old TextMate= grammar) and supports all features up to OCaml 5.4.
  • There is a symbols side panel for each file.
  • You can click on symbols to find definitions and references.
  • You can search for definitions.
  • 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 help= ful. If you encounter any issues with incorrectly highlighted code, this co= uld be a tree-sitter-ocaml issue.

Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/= 2 libraries

Wojtek Czekalski announced

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 s= mall team we ended up maintaining too much software for our liking.

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.

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 combin= ation of those factors resulted in:

  1. Performance regressions in 5.0 related to memory management, both insid= e of app code, SIP stack, and inside of h2.
  2. We needed a more robust implementation of gRPC to handle errors and edg= e 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 toget= her with decent codegen and robust

Then, in late 2025, we had to add new features to the SIP server and someth= ing inside us just broke. The SIP server had accumulated quite a bit of leg= acy code over 3.5 years, so we wanted to rewrite some parts. We were extrem= ely excited to build the new architecture centered around effects — <= a href=3D"https://discuss.ocaml.org/t/effect-composability-actual-callstack= -vs-syntactic-scope/17536">only to discover that user-space effects and con= currency libraries don't really work well together, since callbacks los= e their scope (duh). That was the final straw.

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.

So here we are — we're gradually removing OCaml from our stack, and t= hat's why we'd like to donate:

  • ocaml-grpc= - the new code is on dialo branch, eio only at the moment= , battle tested on production. It does have some bugs in it but few and it'= s pretty solid.
  • haha (http2) - overall = good but could be better. We cancel fibers too often, it's a very low hangi= ng fruit to make it much faster.
  • Our SIP stack — this is currently not open source, but we're happ= y to share the source code with the right person or team.

Please write dms to me and feel free to ask me or @adamchol about specifics.

ppx_mixins: slightly more elegant mixin syntax

Sacha Ayoun announced

Hello,

I've written a tiny ppx called ppx_mixins so that one can write:

type u=
 [@@mixins Map.OrderedType + Printab=
le]

which gets desugared to

type u=

include Map.OrderedType with type t :=3D u
include Printable with type t :=3D u

Not much but increases readability in a codebase that uses the "mixin" patt= ern a lot

Constructing type signatures

In the upcoming release, one can also write

module type M =3D [%mixins Map.<=
/span>OrderedType + Printable]
(* desugars to *)
module type M =3D sig=20
   type t=20
   include Map.OrderedType with type t :=3D t
   include Printable with type t :=3D t
end

Additional features

One can also override other types, e.g.

type u=
 [@@mixins Mappable(key =3D int; val=
ue :=3D v)]
(* desugars to *)
type u
include Mappable with type t :=3D u and type key =3D int and type va=
lue :=3D v

Limitations

  • No support for parametric types, e.g. with type 'a u =3D 'a v
  • 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 t= hese don't parse nicely a expressions. Deeper support (e.g. for mixins with type parameters) would probably also r= equire language support.

Experience Report: Refining Dune=E2=80=99s Dependency Graph

Robin Bate Boerop announced

Refining Dune's Dependency Graph: Per-Module Library Filtering

I've been working on improving Dune's inter-library dependency tracking, an= d wanted to share the experience — both the technical details and wha= t it's like as a first-time contributor to this large open source OCaml pro= ject.

The Problem I Took On

When libA depends on libB, Dune gives every modul= e in libA a glob dependency on all .cmi fi= les in libB. If any .cmi in libB cha= nges, every module in libA is recompiled — even modules = that never reference libB.

For projects with many libraries, this creates a cascade of unnecessary rec= ompilations. The issue that tracks this matter #4572 has been open since 2021.

My Approach

Dune already runs ocamldep to compute intra-library module dep= endencies. 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 fl= ags per-module.

The implementation (PR= #14116 and PR #14= 186) 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 f= lags, partitioning into direct (visible via -I) and hidden (vi= a -H) based on requires_compile membership

With both deps and flags filtered, a clean build will fail if a module refe= rences a library it doesn't declare — previously, overly-broad = -I flags could mask such errors.

A False Start

My first attempt (PR #= 14021) tried to implement the filtering in a single PR without sufficie= nt test coverage. It was closed after review revealed that the approach was= fragile in edge cases I hadn't anticipated — particularly around tra= nsparent module aliases and virtual libraries.

Challenges

Transparent module aliases. OCaml's module alias mechanism means ocamldep doesn't always report all libraries a module transitivel= y depends on. If libB has module M =3D LibC.Something, and a module in libA uses LibB.M, oca= mldep 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 ful= l dependency set.

Virtual libraries. When virtual library implementations are present = in the compilation context, parameter libraries may not appear in req= uires_compile, so filtering could miss them. Another fallback case.

Menhir-generated modules. These mock modules aren't in the oca= mldep dependency graph, so we skip filtering for them.

Null build overhead. The filtering reads .d files and c= omputes library closures per-module. On a fresh dune process (= no memo cache), this is new work on every build — including null buil= ds where nothing changed. This is a real trade-off: better incremental rebu= ild performance at the cost of some null-build overhead.

Prerequisite Test PRs

Before the implementation PRs, I submitted six test-only PRs to document ex= isting behavior and establish a safety net:

  • #14017 —= Baseline tests documenting current inter-library recompilation behavior
  • #14031 —= Test documenting module name shadowing between stanzas and libraries
  • #14100 —= Test verifying library file deps in compilation rules and sandboxed builds=
  • #14101 —= Test verifying transparent alias incremental build safety
  • #14129 —= Test verifying incremental builds with alias re-exported libraries
  • #14178 —= Test documenting ocamldep behavior with transparent alias cha= ins

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.

The Review Process

The Dune maintainers (@rgrinberg and @art-w) provided thorough, = constructive reviews. Some highlights:

  • Replacing my hand-rolled transitive closure with Lib.closure from the existing library — a cleaner approach I wouldn't have fou= nd without familiarity with Dune's internals
  • Identifying that both .ml and .mli ocamldep o= utput need to be read, since the interface can reference different librarie= s than the implementation
  • Suggesting per-module -I~/-H~ flag filtering, which makes = clean builds more precise and improves caching
  • Questioning every fallback case and special-cased module kind, leading = to simpler code

The PRs went through significant refactoring during review — the fina= l versions are substantially tighter than the initial submissions.

What Could Be Better

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 — 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.

Review momentum vs. rebasing. The test PRs merged quickly, but the i= mplementation PR required multiple rounds of review over days. Between roun= ds, main moves forward, requiring rebases that risk introducing conflicts. = The contributor carries the burden of keeping branches fresh. This is compo= unded when PRs depend on each other — every rebase of #14116 required= rebasing #14186 as well. GitHub has no first-class support for PR stacks, = so this is manual and error-prone. Of course, all GitHub-hosted repos suffe= r from this.

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 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.

Reflections

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.

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.

The maintainers have been responsive and the review process, while slowed b= y thoroughness, is collaborative and professional. Thank you, maintainers!

Steffen Smolka then replied

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

octachron announced

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:

  • two runtime bugs (for ephemerons and the bytecode interpreter)
  • two type system bugs (for classes and module-dependent functions)
  • 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 O= Caml 5.5.0 is the most up-to-date resource.

Happy hacking, Florian Angeletti for the OCaml team.

Installation Instructions

The base compiler can be installed as an opam switch with the following com= mands on opam 2.1 and later:

opam update
opam switch create 5.5.0~beta1

The source code for the beta is also available at these addresses:

Fine-Tuned Compiler Configuration

If you want to tweak the configuration of the compiler, you can switch to t= he option variant with:

opam update
opam switch create <switch_name> ocaml-variants.5.5.0~beta1+options &=
lt;option_list>

where option_list is a space separated list of ocaml-opt= ion-* packages. For instance, for a flambda and no-flat-float-array = switch:

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

All available options can be listed with opam search ocaml-option.

Changes compared to the last alpha

  • Documentation update
    • #14684: Imp= rove ocamlopt's manual page (Samuel Hym, review by Florian Angeletti)
  • Runtime fixes
    • #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)
    • #14349, #14718: runtime, f= ix in the orphaning of ephemerons (Gabriel Scherer, review by Olivier Nicole and Damien Doligez, report by Jan Midtgaard)
  • Type system fixes
    • #14557, #12150, #14696: ensure that the s= elf type of class cannot escape through type constraints. (Leo White, review by Florian Angeletti)
    • #14667: ena= ble application related warnings for module-dependent functions (Florian Angeletti, review by Gabriel Scherer)
  • Error messages and warning fixes
    • #14690: Fix= Name_type_mismatch 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)
    • #14719, #14721: compute ar= ity correctly for module-dependent function (Florian Angeletti, report by Jeremy Yallop, review by Stefan Muenzel)
    • #14655, #14691: check for = size overflow in caml_ba_reshape (Stephen Dolan, review by Xavier Leroy)

ocgtk 0.1: OCaml bindings for GTK 4 (preview release)

Continuing this thread, Chris Armstrong announced

ocgtk preview1 release has landed in opam.

(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.

In addition to the features above, it includes:

  • Extended support for more GLib types, including integer primitives (gui= nt8, int16, guint32, etc) and lists (GLib.SList and GLib.List)
  • Gobject interfaces

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).

Next steps: 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)

Old CWN

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a loo= k at the archive or the <= a href=3D"https://alan.petitepomme.net/cwn/cwn.rss">RSS feed of the archive= s.

If you also wish to receive it every week by mail, you may subscribe to the= caml-list.

--==-=-=-- --=-=-=-- --===-=-= 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----- --===-=-=--