OCaml - Latest posts https://discuss.ocaml.org Latest posts [ANN] valkey: modern Valkey client for OCaml 5 + Eio, on opam Hi everyone,

I wanted to share that valkey 0.2.0 is now on opam:

The main thing I wanted with this project was to focus on the current Valkey stack with the newer OCaml stack.

So valkey is built around:

  • OCaml 5
  • Eio-native direct-style concurrency
  • RESP3 only
  • Modern Valkey features and real cluster behavior

A few parts I’m happy with:

  • Cluster support with a strong focus on durability and high availability:
    topology refresh, periodic background refresh, MOVED / ASK / CLUSTERDOWN handling, replica-aware reads, AZ-aware routing, and failover-aware sharded pub/sub replay

  • connection/runtime behavior:
    circuit breaker, reconnect handling, keepalive, TLS, and optional separation between socket I/O and parsing via Eio.Domain_manager, so one side of the system does not block the other

  • batch support:
    scatter-gather across slots, atomic single-slot flows with WATCH / MULTI / EXEC, multi-slot helpers, and in
    0.2.0 also WATCH guards for read-modify-write CAS plus cross-slot pfcount_cluster

  • command surface:
    typed helpers across a pretty broad set of commands, Client.custom /custom_multi for custom commands and multi-node execution, and named commands so you can register command templates once and reuse them later

  • scripting:
    local script caching and optimistic EVALSHA handling with automatic fallback/retry on NOSCRIPT, so callers don’t need to manage that flow themselves

There is also already a pretty good amount of validation around it:
integration tests, property tests, fuzzing, chaos testing, examples, and guides.

Performance-wise, it also came out pretty nicely: in several scenarios it gets to 90%+ of the C reference client.

opam update
opam install valkey eio_main

Current next steps on the roadmap are things like:

  • client-side caching
  • connection pools / blocking pools
  • IAM + mTLS
  • Valkey module support (JSON, search, bloom)

If there’s a feature people care about, I’d be very happy to reprioritize the roadmap around real interest.

I’d also really love feedback from the OCaml community on the API, ergonomics, docs, and general design.

I’m very familiar with the Valkey world, but OCaml is more of a side fun for me than my daily language, so feedback from people who really live in the OCaml ecosystem is especially valuable to me.

If you try it, I’d love to hear what you think.

]]>
https://discuss.ocaml.org/t/ann-valkey-modern-valkey-client-for-ocaml-5-eio-on-opam/18010#post_1 Thu, 23 Apr 2026 01:01:31 +0000 discuss.ocaml.org-post-76216
[ANN] ocaml-wire: a Binary wire format DSL with EverParse 3D output I’m happy to announce the release of ocaml-wire 0.9.0 to opam!

ocaml-wire is a set of combinators to describe binary protocols in OCaml. “Binary” as in fixed-layout: sizes and shapes are mostly known up front, so you’re reading fields at known offsets rather than parsing a free-form grammar (like in Menhir). There are already many good binary parser frameworks in OCaml – here’s what’s different in ocaml-wire:

  • The central data structure is EverParse’s 3D grammar. The OCaml combinators describe a 3D structure. Following Daniel’s tagged final encoding approach, you build a codec that describes a struct and how to serialise/deserialise it from an OCaml value.
  • Which means every description can compile down to a .3d file and from there to C via EverParse – and the generated C compiles cleanly with -std=c99 -Wall -Werror. So you could, in theory (I haven’t pushed on this too far for now), build and link a complex stack as an standalone, external C parser whose memory safety, single-pass behaviour, and conformance to the 3D spec are proven in F*(EverParse doesn’t give you serialisers, unfortunately).
  • If you prefer, you can still use the OCaml parsers/verifiers, which have been made reasonably fast (i.e. no extra allocations on the hot path), and as they are streaming codecs you can just read or write a single field of the structure without parsing the whole thing. They also compile trivially to JavaScript via js_of_ocaml, if you need to parse the same format in the browser.

A small example – a packet with two nibble-wide fields, a big-endian length, and a variable-size payload whose length is read from the Length field:

open Wire

type packet = { version : int; flags : int; length : int; payload : string }

let f_version = Field.v "Version" (bits ~width:4 U8)
let f_flags   = Field.v "Flags"   (bits ~width:4 U8)
let f_length  = Field.v "Length"  uint16be
let f_payload = Field.v "Payload" (byte_array ~size:(Field.ref f_length))

let codec =
  let open Codec in
  v "Packet" (fun version flags length payload -> { version; flags; length; payload })
    [ f_version $ (fun p -> p.version);
      f_flags   $ (fun p -> p.flags);
      f_length  $ (fun p -> p.length);
      f_payload $ (fun p -> p.payload) ]

Field.ref f_length is the dependent-size bit: the payload’s length comes from the f_length field read earlier in the same struct. That same codec value is what you hand to Everparse.schema to get the 3D file out, and what backs Codec.get / Codec.set for streaming field access from OCaml. ocaml-wire also ships the infrastructure for generating FFI stubs and for differential testing to make sure the verified C and hand-written OCaml parsers agree. So far they seem to :slight_smile:

You can read more about it here: Thomas Gazagnaire :: Describing Binary Formats in OCaml.

To try it: opam install wire

Feedback very welcome on the issue tracker (or bellow)!

]]>
https://discuss.ocaml.org/t/ann-ocaml-wire-a-binary-wire-format-dsl-with-everparse-3d-output/18009#post_1 Wed, 22 Apr 2026 21:13:58 +0000 discuss.ocaml.org-post-76215
Experience Report: Refining Dune’s Dependency Graph
lindig:

Does Dune detect that a file is unchanged based on a hash or file attributes and can re-use dependency information?

Yes, all 3. It uses file modification time to decide whether other changes must be checked for. It uses hashes to confirm change and to enable early cut-off. It re-uses dependency information across runs by caching dependency information.

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_9 Wed, 22 Apr 2026 16:31:00 +0000 discuss.ocaml.org-post-76214
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository Hi! Sorry about this, the constraint was discovered during the release and I guess I just changed >= “5.2” to = “5.2” without thinking about it.

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_10 Wed, 22 Apr 2026 09:40:02 +0000 discuss.ocaml.org-post-76213
Experience Report: Refining Dune’s Dependency Graph
art-w:

This is most likely where the 70% regression on null builds was observed:

Does Dune detect that a file is unchanged based on a hash or file attributes and can re-use dependency information?

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_8 Wed, 22 Apr 2026 08:48:23 +0000 discuss.ocaml.org-post-76212
Closing Old Bugs With Tests: A Dune Contribution Story I recently started contributing to Dune with no prior familiarity with the code base. One thing I found rewarding was closing old issues — some filed as far back as 2018 — and I wanted to share the approach I used.

The Method: Close With a Test

Many open issues describe behaviour that has already been fixed, or behaviour that is working correctly but was never verified with a test. My approach: write a cram test that demonstrates the expected behaviour, link the PR to the issue with fixes #NNNN, and let the merge close the issue automatically.

This has several advantages over simply closing an issue with a comment like “this works now”:

  • It’s verifiable. Anyone can read the test and see exactly what behaviour is being asserted. There’s no argument about whether the issue is truly resolved.
  • It prevents regressions. If the behaviour breaks again in the future, the test fails. The issue doesn’t silently reopen — the CI catches it.
  • It grows the test suite. Every closed issue leaves behind a test that documents a real-world scenario someone cared about.
  • It respects the reporter. Someone took the time to file the issue. A test that captures their concern is a better acknowledgement than a drive-by close.

After a few weeks of contributing test PRs and bug fixes, I was given triager and then maintainer status on the project. This let me close issues directly when they were clearly resolved, and merge my own test PRs. Before that, the existing maintainers merged them on my behalf.

Honestly, I regret closing issues where I could have used this method but didn’t. The method is much superior to simply adding to a GitHub discussion about the bug and then closing the issue.

Issues I Helped Close

Here’s an accounting of what I helped close, grouped by what it took:

Confirmed resolved; closed directly

These issues described problems that no longer existed on main. In some cases I confirmed this myself, in others someone else had already verified it. As a triager/maintainer I was able to close them:

  • #1974@all target doesn’t interact well with (include_subdirs ...) (filed 2019)
  • #3173 — Can’t promote into a directory starting with underscore (filed 2020)
  • #3805 — No such file or directory when DUNE_BUILD_DIR is set during test (filed 2020)
  • #8242 — Very slow emacs compilation buffer updates (filed 2023)
  • #10360executables_implicit_empty_intf expects dune >= 2.9 but was only added in 3.0 (filed 2024)

Closed with a test PR

These issues were resolved by writing a test that demonstrates the correct behaviour. No code changes were needed — the test itself closed the issue:

  • #2370.h files copied to _build without foreign stubs (filed 2019, test: #14172)
  • #3362 — Cannot use %{lib:...} in the flags stanza (filed 2020, test: #14146)
  • #3484 — Promoting over a running binary (filed 2020, test: #14173)
  • #11110 — Libexec site install doesn’t set executable bit (filed 2024, test: #14171)

Closed with a test and a code fix

These required both a test and a code change to resolve:

  • #878dune subst adds duplicate version field in opam (filed 2018, fix: #14136)
  • #2445 — dune sends SIGKILL without prior SIGTERM (filed 2019, fixes: #14170, #14224)
  • #3916 — Duplicate bounds in autogenerated opam files (filed 2020, fix: #14175)
  • #6148root_module generates duplicate module definition (filed 2022, fix: #14135)
  • #9757dune runtest doesn’t execute byte-only inline tests (filed 2024, fix: #14174)
  • #10707 — Missing menhir lower bound in generated opam files (filed 2024, fix: #14168)
  • #11002 — opam file generation error-prone (filed 2024, fix: #14136)
  • #11106 — Redundant dune version constraint in opam files (filed 2024, fix: #14175)
  • #12007dune build @ocaml-index builds too many files (filed 2025, partially fixed with #14137)
  • #14089 — Incremental builds with (wrapped (transition ...)) broken (filed 2026, test: #14088, fix: #14090)

What I Learned

Writing tests is a good way to learn about a code base. Each test forced me to understand how a feature actually works — not the architecture in the abstract, but the concrete behaviour in specific scenarios. The understanding compounded.

Dune’s cram tests make this easy. Each test is a self-contained shell script with expected output, checked into the repo as a .t file. The barrier to writing a test is low, which is exactly what you want when your goal is to close issues by testing them. This occasionally backfired by being “too easy” - when I wrote tests to which maintainers objected because I had not done so in a Dune-idiomatic way; but this was still net positive for sure.

Consistent presence matters. I contributed nearly every day over several weeks. I think that this helped maintainers feel that I was “present” - that efforts that they made to help me were investments; so they were less prone to holding back reviews.

]]>
https://discuss.ocaml.org/t/closing-old-bugs-with-tests-a-dune-contribution-story/18008#post_1 Tue, 21 Apr 2026 22:01:29 +0000 discuss.ocaml.org-post-76211
Experience Report: Refining Dune’s Dependency Graph Note that this work is not yet merged, nor necessarily guaranteed to merge. It surfaces problems that must first be addressed, or at least understood.

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_7 Tue, 21 Apr 2026 21:07:23 +0000 discuss.ocaml.org-post-76210
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository
hannes:

What would be the perfect message?

in this particular case something like:

“lwt_lint.0.1” depends on unknown package version: “ocaml” { = “5.2” }

but i suspect it is hard to do in practice

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_9 Tue, 21 Apr 2026 16:10:47 +0000 discuss.ocaml.org-post-76209
Empty polymorphic variant type? But outside the module it behaves like an empty type, because the module as defined doesn’t export such a thing.

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_17 Tue, 21 Apr 2026 16:02:14 +0000 discuss.ocaml.org-post-76208
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository What would be the perfect message?

And, for these packages, I suspect that the opam-repo-ci could give some better feedback – it should fail to pass if such unsatisfied dependencies are around. Well, I’m not sure whether opam-repo-ci is the thing to report such an issue, but a tool very similar to archive-opam (in terms of figuring out what is available) may be worth investigating.

For the short-term, what should be done with these packages @Juloo? What is the right constraint? Is it 5.2.0 or something else?

Another issue appearing is “diffast-langs-…” with "unsatisfied dependency “threads” – I guess using “base-threads” instead would solve the issue? But then, there’s been no complaint / issue report, so who’d care about it?

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_8 Tue, 21 Apr 2026 15:05:50 +0000 discuss.ocaml.org-post-76207
[ANN] New release of OCaml LSP 1.26.0 & Merlin 5.7.0-504 Hello, on the change log page :

OCaml Changelog,

the date is “4 Oct 2026” which is in the future.

I suppose that it should be 10 Apr 2026 :wink:

]]>
https://discuss.ocaml.org/t/ann-new-release-of-ocaml-lsp-1-26-0-merlin-5-7-0-504/17978#post_2 Tue, 21 Apr 2026 15:02:35 +0000 discuss.ocaml.org-post-76206
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository The tool is correct (although the message isn’t perfect).
It is unsatisfied because there is no version of the ocaml package with version 5.2. There is a version 5.2.0 but no 5.2. Subtly different but not equal under opam’s version specification.

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_7 Tue, 21 Apr 2026 13:18:00 +0000 discuss.ocaml.org-post-76205
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository same remark for ciao_lwt (which i think is part of the same effort by @Juloo ?)

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_6 Tue, 21 Apr 2026 12:48:49 +0000 discuss.ocaml.org-post-76204
[ANN] Mollymawk and Albatross orchestrating all virtual machines
hannes:

Now, BHyve in my perspective performs well, works nicely, and has its limitations: when I first tried on my laptop I couldn’t execute more than 1600 virtual machines (doing the MirageOS unikernel development) – I asked the original author, and he mentioned that this is uncharted territory. In production, I do run fewer virtual machines, and I don’t run into issues there.

Really appreciate your response regarding BHyve and FreeBSD in general.

I also use FreeBSD occasionally and agree with a lot of the points you made in your reply. I use vm as the Bhyve front end and while basic, it gets the job done.

I have to say, I don’t understand how people can run services and laptops without such a snapshottable file system. Updating is easy. Backups are easy.

The same thing is definitely possible in Linux via btrfs snapshots – there are some utilities available that ease the whole process. However the simplicity of FreeBSD’s bectlexperience is unbeatable.

I tried to use GNU/Linux as my daily driver, and was overwhelmed by the number of daemons that are running, and how to figure out where the source code of something is and how to compile it (as a package) feels very tricky to me. Also, their system of initrd etc. is very complex to my brain.

I came into FreeBSD from Linux. I would say that FreeBSD is an excellent system but not any less complex than Linux. It’s just a matter of getting used to things. I personally love Fedora and Chimera Linux (incidentally Chimera Linux is quite similar in philosophy to FreeBSD in the Linux world).

For me, learning to use FreeBSD has been a very pleasant experience. Once you use ZFS you understand what the fuss is about. You also realise the value of a cohesive system in which kernel and userspace are developed together. It’s also great that clang is the FreeBSD system compiler and the FreeBSD libc is so simple in comparison to Linux’s glibc. (musl libc is quite good though).

To anybody reading this I would recommend trying out FreeBSD. It will give your unix/computing concepts a nice boost. I still prefer Linux but I love FreeBSD too :slight_smile: .

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_12 Tue, 21 Apr 2026 12:48:01 +0000 discuss.ocaml.org-post-76203
[archival] [ann] Raising the OCaml lower bound to 4.11.0 for opam-repository There’s the line

“lwt_lint.0.1” unsatisfied dependency: “ocaml” { = “5.2” }

which suggests that lwt_lint is removed because its bound is ocaml=5.2 (which I just checked in the opam-repo and it’s what it says there too).

is that an issue with the archival selection tool?
or is it archived for a different reason (what) and this just shows ocaml constraint for a some reason (what?)?

]]>
https://discuss.ocaml.org/t/archival-ann-raising-the-ocaml-lower-bound-to-4-11-0-for-opam-repository/17965#post_5 Tue, 21 Apr 2026 12:47:48 +0000 discuss.ocaml.org-post-76202
[ANN] Mollymawk and Albatross orchestrating all virtual machines I use since more than two decades FreeBSD as my daily driver, and also on servers I maintain.

Since more than a decade I use the zfs file system (ZFS - Wikipedia) – nowadays available on GNU/Linux via OpenZFS as well. I do use geli for encryption of drives (plus some testruns of zfs encryption).

I have to say, I don’t understand how people can run services and laptops without such a snapshottable file system. Updating is easy. Backups are easy. Documentation is great.

Also, when it comes to documentation, whenever I’m unsure I look up in the FreeBSD handbook (FreeBSD Handbook | FreeBSD Documentation Portal) – a well-wrtitten, up-to-date book on how to configure FreeBSD. I also find the manual pages very well written and understandable.

Why I use FreeBSD is as well that to me it feels like home, I have an easy time to debug and change the system I’m using, compiling a new kernel (or a user-space utility) without any fuzz (as example, recently I had to connect to a wireless network with enterprise (802.1x) authentication, and it used legacy ciphers – so I needed to change the call in wpa_supplicant to OpenSSL – I wouldn’t know where to start and what to do on a Linux system). Various utilities are shipped with the base system, which makes the pure base already very usable (ifconfig / tcpdump / …).

I tried to use GNU/Linux as my daily driver, and was overwhelmed by the number of daemons that are running, and how to figure out where the source code of something is and how to compile it (as a package) feels very tricky to me. Also, their system of initrd etc. is very complex to my brain.

I do understand and appreciate that other people are using and are happy with their Linux systems. It’s just not my cup of tea.

Now, BHyve in my perspective performs well, works nicely, and has its limitations: when I first tried on my laptop I couldn’t execute more than 1600 virtual machines (doing the MirageOS unikernel development) – I asked the original author, and he mentioned that this is uncharted territory. In production, I do run fewer virtual machines, and I don’t run into issues there.

Obviously the development of FreeBSD (similar to Linux as far as I understand) is driven a lot by commercial users who employ developers (for FreeBSD, this is for sure NetApp, Netflix, etc. – take a look at Donors | FreeBSD Foundation is this is interesting.

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_11 Tue, 21 Apr 2026 11:22:10 +0000 discuss.ocaml.org-post-76201
Empty polymorphic variant type? This is not a empty type, since the module could construct

let rec x = `B x

If you want to test that you are defining a provably empty type, you can ask the typechecker directly with an unreachable clause. For instance, this compiles fine:

type empty = |
type t = [ `E of empty ]
let really_empty (x:t) = match x with `E _ -> .

Contrarily, this code

module Empty : sig
  type t = private [ `B of t ]
end = struct
  type t = [ `B of t ]
  let rec x = `B x
end
let not_empty (x:Empty.t) = match (x:> [`B of Empty.t]) with `B _ -> .

fails with

Error: This match case could not be refuted.
Here is an example of a value that would reach it: `B _

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_16 Tue, 21 Apr 2026 08:10:51 +0000 discuss.ocaml.org-post-76200
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries Would it make sense to contribute the SIP server to the Mirage organisation ( MirageOS · GitHub )?
Assuming the implementation could be open sourced under a compatible license. They already have RFC implementations for various protocols, adding a SIP implementation seems like a natural fit.

]]>
https://discuss.ocaml.org/t/seeking-maintainers-for-our-ocaml-sip-server-grpc-and-http-2-libraries/18000#post_3 Tue, 21 Apr 2026 03:34:01 +0000 discuss.ocaml.org-post-76198
Empty polymorphic variant type? Apparently the following also works:

  module Empty : sig
    type t = private [ `B of t ]
  end = struct
    type t = [ `B of t ]
  end

Who knew there were so many ways to define an empty type!

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_15 Tue, 21 Apr 2026 01:12:56 +0000 discuss.ocaml.org-post-76197
[ANN] ocgtk 0.1: OCaml bindings for GTK 4 (preview release) 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:

  • Extended support for more GLib types, including integer primitives (guint8, int16, guint32, etc) and lists (GLib.SList and GLib.List)
  • 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)

]]>
https://discuss.ocaml.org/t/ann-ocgtk-0-1-ocaml-bindings-for-gtk-4-preview-release/17944#post_5 Mon, 20 Apr 2026 22:51:55 +0000 discuss.ocaml.org-post-76196
Empty polymorphic variant type? I think this one works, too:

module rec Empty :
sig
  type t
  val abort : t -> 'a
end = Empty
]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_14 Mon, 20 Apr 2026 22:46:14 +0000 discuss.ocaml.org-post-76195
Empty polymorphic variant type? For sure, because OCaml is a call-by-value language. If you look at the blog article I linked, in Haskell, which is a call-by-name language, you could write this equivalent OCaml code:

let rec empty : 'a. a = empty

and that’s the use-elimination of empty that leads to a divergent computation, as in your code example: try abort empty with your implementation and you will have a divergent computation. @yallop and your Haskellish solution are dual : in one case the divergence is in the introduction principle, in the other it’s in the elimination one.

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_13 Mon, 20 Apr 2026 22:20:28 +0000 discuss.ocaml.org-post-76194
Experience Report: Refining Dune’s Dependency Graph Yeah, this is probably the main issue with scaling this optimization to larger workspaces. In fact, even without this optimization, this is an area that dune handles poorly. This optimization just exposes this weakness more.

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_6 Mon, 20 Apr 2026 22:12:39 +0000 discuss.ocaml.org-post-76193
Experience Report: Refining Dune’s Dependency Graph Thanks, @art-w and @gasche for your ideas. Yes, this re-computation of closures is inefficient and @rgrinberg has already produced a commit that I have cherry-picked into the 14116 branch. It seems to make a difference, but not by much (6.6 seconds null build versus 4.0 on ‘main’). The investigation continues (and the discussion remains on GitHub).

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_5 Mon, 20 Apr 2026 22:08:13 +0000 discuss.ocaml.org-post-76192
Empty polymorphic variant type? That was my first reaction too, but I think there’s a difference: your make_empty is a function whose return type is empty, but if you actually call it, it never returns. If you try to define let x = make_empty () then it will compile, but if it will blow up if you run it. Whereas @amongonz 's empty will actually return: it’s a cyclic data structure, not a divergent computation.

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_12 Mon, 20 Apr 2026 20:54:40 +0000 discuss.ocaml.org-post-76191
Empty polymorphic variant type? That’s because in a turing complete language (with full recursion) any type is inhabited, see for instance How many values does a boolean have?, especially the paragraph about Haskell and bottom which is similar to the solution of @viritrilbia. Bottom is the denotation of non terminating computation.

In OCaml, you can inhabit the type empty like this:

type empty = |
let rec make_empty () = (make_empty () : empty)

In other words, in @yallop solution the production-introduction of a bottom value leads to non termination (make_empty ()), whereas in @viritrilbia that’s the use-elimination of such a value that lead to non termination (abort empty) : they are dual point of view.

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_11 Mon, 20 Apr 2026 20:30:09 +0000 discuss.ocaml.org-post-76190
Empty polymorphic variant type? Thank you! You’re right, those modifications work. And for completeness, here is a definition, using that approach, of a family of finite types of all cardinalities that are related by subtyping:

type empty = |
type zero = [ `Empty of empty ]
type 'a suc = [ `Zero | `Suc of 'a | `Empty of empty ]

Then zero < zero suc < zero suc suc < …

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_10 Mon, 20 Apr 2026 16:58:45 +0000 discuss.ocaml.org-post-76189
First beta release of OCaml 5.5.0 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 OCaml 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 commands
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 the option variant with:

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

where option_list is a space separated list of ocaml-option-* 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+options 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: Improve 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ás Ojeda Bär, Stephen Dolan and Olivier Nicole)

  • #14349, #14718: runtime, fix 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 self type of class cannot escape
    through type constraints.
    (Leo White, review by Florian Angeletti)

  • #14667: enable 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 arity 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)

]]>
https://discuss.ocaml.org/t/first-beta-release-of-ocaml-5-5-0/18006#post_1 Mon, 20 Apr 2026 14:47:10 +0000 discuss.ocaml.org-post-76188
[ANN] Mollymawk and Albatross orchestrating all virtual machines Sorry, I haven’t started using VM, I am still in the process of defining what I will run and how.

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_10 Mon, 20 Apr 2026 14:00:19 +0000 discuss.ocaml.org-post-76187
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries Would it make sense to move them under the OCaml Community · GitHub umbrella organization? it’s already home to ~20 libraries and projects forked by or donated to “the community”. Members of the organization are well-established maintainers of the opam-repository, or have been around for some time.
Have a look at the org’s manifesto: GitHub - ocaml-community/meta: Administration and documentation for the ocaml-community organization. · GitHub.
It’s also possible to host the libraries there and get write access to specific repositories without being a member of ocaml-community GitHub’s organization.

]]>
https://discuss.ocaml.org/t/seeking-maintainers-for-our-ocaml-sip-server-grpc-and-http-2-libraries/18000#post_2 Mon, 20 Apr 2026 11:49:09 +0000 discuss.ocaml.org-post-76186
[ANN] Mollymawk and Albatross orchestrating all virtual machines
hannes:

I won’t go into the “FreeBSD vs Linux” discussion in here, I’m sure there are plenty of (opinionated) resources available that will help you to get a top level insight.

Thanks ! Ok I understand that you don’t want to get drawn into any FreeBSD/Linux comparison.

In my experience there is often poor quality information available about OSes other than Linux/Windows on the internet. The usage of FreeBSD is quite miniscule so that is to be expected.

I’m not interested in benchmarks… rather your general experience with bhyve if you’d like to share that with everyone. No need to compare with Linux if you don’t want to.

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_9 Mon, 20 Apr 2026 09:25:12 +0000 discuss.ocaml.org-post-76183
[ANN] Code navigation and search on Github Nice! I did notice something had improved. Thank you for that.

]]>
https://discuss.ocaml.org/t/ann-code-navigation-and-search-on-github/17999#post_2 Mon, 20 Apr 2026 09:23:08 +0000 discuss.ocaml.org-post-76182
[ANN] Mollymawk and Albatross orchestrating all virtual machines So what is your current invocation how you start a virtual machine? Is it using qemu? What kind of parameters do you pass?

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_8 Mon, 20 Apr 2026 09:10:16 +0000 discuss.ocaml.org-post-76181
[ANN] Mollymawk and Albatross orchestrating all virtual machines Thanks for your interest. I didn’t conduct any benchmarks, but I’m sure you’ll find some on the Internet or be able to conduct some yourself.

I won’t go into the “FreeBSD vs Linux” discussion in here, I’m sure there are plenty of (opinionated) resources available that will help you to get a top level insight.

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988#post_7 Mon, 20 Apr 2026 08:51:21 +0000 discuss.ocaml.org-post-76180
Empty polymorphic variant type? It’s easy enough to adapt that approach to use actually empty types, though, e.g. with a empty variant

type nothing = |
type empty = [`Empty of nothing ]
let abort : type a. empty -> a = function `Empty _ -> .

or a polymorphic record field:

type nothing = { abort: 'a. 'a }
type empty = [`Empty of nothing ]
let abort : type a. empty -> a = function `Empty { abort } -> abort

or an equality GADT with incompatible types:

type empty = [`Empty of ([`A], [`B]) Type.eq ]
let abort : type a. empty -> a = function `Empty _ -> .
]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_9 Mon, 20 Apr 2026 08:25:38 +0000 discuss.ocaml.org-post-76179
Experience Report: Refining Dune’s Dependency Graph Welcome to dune development and many thanks for your PRs!

It’s very discrete because it’s generally green, but the CI also ran ocaml-benchmarks on your PRs :slight_smile: This is most likely where the 70% regression on null builds was observed: CI benchmarks for #4572 (4s to 7s on dune codebase itself for null builds, no changes for clean builds).

As noted by @rgrinberg, we’ll need to fix this regression before being able to merge your PRs: A null build (= no changes) roughly measures the minimum amount of analysis that dune needs to do to realize that there’s nothing to do (!)… so in their current state, the PRs would make every build slower to enable an optimization that doesn’t save as much time in general (*). Fortunately @gasche 's insight is spot on! (Currently the transitive closures are recomputed from scratch for every module, with no reuse of the redundant work… I’m hopeful that we can fix it!)

(*) @rgrinberg gave an example of two modules where we would have expected a speedup, one depending on a “slow” library that takes a lot of time to build and the other depending on a “fast” library. Before your PRs, observing the build on two cores would have looked like:

CPU1: [build slow library .......] -> [build use_slow.ml .....]
CPU2: [build fast lib]             -> [build use_fast.ml] (waiting for "slow")

With the more precise analysis of library dependencies per module, the build of use_fast.ml doesn’t need to wait for the slow library to finish building:

CPU1: [build slow library .......] -> [build use_slow.ml .....] |
CPU2: [build fast lib] -> [build use_fast.ml]                   |
                                                                | build done!

So sadly, given the pre-existing opportunities for build concurrency, the total build time remains the same in this example. But we are still interested by this optim because it does improve the build graph with more opportunities for concurrency and caching! Concretely in the example, it would speedup things if use_fast.ml was the one with a slow compile time; and on an incremental change to the “fast” lib, skipping the use_slow.ml unnecessary rebuild would also be more efficient :slight_smile:

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_4 Mon, 20 Apr 2026 08:03:10 +0000 discuss.ocaml.org-post-76177
Empty polymorphic variant type? It’s actually possible to write:

let rec empty : empty = `Empty empty

which without the annotation gets type [> `Empty of 'a ] as 'a, so it isn’t really an empty type.

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_8 Mon, 20 Apr 2026 07:39:21 +0000 discuss.ocaml.org-post-76176
Empty polymorphic variant type? I have just discovered that there do exist polymorphic variant types that are semantically empty even if they are not syntactically empty, such as

type empty = [ `Empty of empty ]

This type has a constructor, but due to the recursion it is not possible to actually construct an element of it, and we can prove that it satisfies the eliminator of the empty type:

let rec abort : type a. empty -> a = function (`Empty e) -> abort e

This doesn’t achieve the general goal of having one polymorphic variant type that is a subtype of every other such. But I think if you have control over the other polymorphic variant types you’re using, you should be able to add the constructor `Empty of empty to all of them, causing them to contain empty as a subtype without adding any actual elements to them. (Although that would require adding an extra `Empty e → abort e clause to any match on them.)

]]>
https://discuss.ocaml.org/t/empty-polymorphic-variant-type/8467#post_7 Mon, 20 Apr 2026 06:57:59 +0000 discuss.ocaml.org-post-76175
Experience Report: Refining Dune’s Dependency Graph Fascinating report! I am curious about the efficiency impact of repeated transitive-closure computations. Can you link to the CI benchmark reports and the discussions of the efficiency cost?

I would assume that it is reasonably easy to cache transitive dependency computations. In particular, if a module A depends on C and D, you don’t need to compute the closure of {C, D}, you can compute the closure of C and the closure of D, and union them. Then if B depends on D and E, all the work computing the closure of D can be shared. You need to compute dependency closure at most once per dependency, so intuitively it should be the same amount of work to compute dependencies of a whole library (set of modules) or compute dependencies of each of its modules separately.

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_3 Mon, 20 Apr 2026 05:09:52 +0000 discuss.ocaml.org-post-76174
Experience Report: Refining Dune’s Dependency Graph
robinbb:

GitHub has no first-class support for PR stacks

It does now: GitHub Stacked PRs | GitHub Stacked PRs

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_2 Sun, 19 Apr 2026 23:48:26 +0000 discuss.ocaml.org-post-76173
Experience Report: Refining Dune’s Dependency Graph 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 — 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

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

My Approach

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 — 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 sufficient test coverage. It was closed after review revealed that the approach was fragile in edge cases I hadn’t anticipated — particularly around transparent module aliases and virtual libraries.

Challenges

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

Before the implementation PRs, I submitted six test-only PRs to document existing 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 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.

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 found without familiarity with Dune’s internals
  • Identifying that both .ml and .mli ocamldep output need to be read, since the interface can reference different libraries 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 final 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. 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 — 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

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!

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002#post_1 Sun, 19 Apr 2026 20:23:54 +0000 discuss.ocaml.org-post-76172
[ANN] ppx_mixins: slightly more elegant mixin syntax Hello,

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

type u [@@mixins Map.OrderedType + Printable]

which gets desugared to

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

Not much but increases readability in a codebase that uses the “mixin” pattern a lot

Constructing type signatures

One can also write

module type M = [%mixins Map.OrderedType + Printable]`
(* desugars to *)
module type M = sig 
   type t 
   include Map.OrderedType with type t := t
   include Printable with type t := t
end

In particular, if you also overcome the lack of support for e.g. pretty printing (or other features) in the standard library by extending functors:

module type Hashed_and_printable = sig
   include Stdlib.Hashtbl.HashedType
   val pp : Format.formatter -> t -> unit
end

module Make (T: Hashed_and_printable) = struct 
   include Stdlib.Hashtbl.Make(T)
   let pp = ...
end

You can instead write:

module Make(T: [%mixins Stdlib.Hashtbl.HashedType + Printable]) = struct 
   ...
end

Additional features

One can also override other types, e.g.

type u [@@mixins Mappable(key = int; value := v)]
(* desugars to *)
type u
include Mappable with type t := u and type key = int and type value := v

Limitations

  • No support for parametric types, e.g. with type 'a u = 'a v
  • No support for tuple and function types, e.g. with type t = 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.

]]>
https://discuss.ocaml.org/t/ann-ppx-mixins-slightly-more-elegant-mixin-syntax/18001#post_1 Sun, 19 Apr 2026 13:22:52 +0000 discuss.ocaml.org-post-76171
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries 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

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 — only to discover that user-space effects 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 — we’re gradually removing OCaml from our stack, and that’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 hanging fruit to make it much faster.
  • Our SIP stack — 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.

]]>
https://discuss.ocaml.org/t/seeking-maintainers-for-our-ocaml-sip-server-grpc-and-http-2-libraries/18000#post_1 Sat, 18 Apr 2026 12:37:09 +0000 discuss.ocaml.org-post-76170
[ANN] Code navigation and search on Github GitHub is now using tree-sitter-ocaml for code navigation and code search.

  • 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 helpful. If you encounter any issues with incorrectly highlighted code, this could be a tree-sitter-ocaml issue.

]]>
https://discuss.ocaml.org/t/ann-code-navigation-and-search-on-github/17999#post_1 Sat, 18 Apr 2026 12:15:26 +0000 discuss.ocaml.org-post-76169
[ANN] Parseff: parser combinator library for OCaml 5 Hard to say, because they aren’t comparable or at least I have no idea how to do it.

Mostly because menhir is a parser generator and it will be used inside a pipeline with a Lexer, while parseff (or any parser combinator) often is used to parse strings; you could do Source.of_function and have some lexer producing tokens but still they are solving different problems.

Any parser combinator has backtracking, and it builds up from small functions, conflicts don’t exist while menhir is more like a monolithic "table-driven shift/reduce on a stream of tokens) which doesn’t compose with the rest of your program and has an implicit error mechanism.

If you compare them somehow it will depend on the syntax as well, and in the menhir’s case you might need to ignore the lexing time? Anyway, no idea how to make justice here, hope it helps

]]>
https://discuss.ocaml.org/t/ann-parseff-parser-combinator-library-for-ocaml-5/17914?page=2#post_34 Fri, 17 Apr 2026 18:38:15 +0000 discuss.ocaml.org-post-76168
[ANN] Parseff: parser combinator library for OCaml 5 Dumb question: how does it compare to menhir in terms of performance?

]]>
https://discuss.ocaml.org/t/ann-parseff-parser-combinator-library-for-ocaml-5/17914?page=2#post_33 Fri, 17 Apr 2026 17:26:03 +0000 discuss.ocaml.org-post-76167
[ANN] Restarting OCaml.jp: The OCaml Japan User Group 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.

Current Activities

We’ve already kicked off a couple of initiatives:

  • OCaml Weekly News - Japanese Edition: We’re maintaining a Japanese 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.

  • 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 soon; 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. よろしくお願いします!

]]>
https://discuss.ocaml.org/t/ann-restarting-ocaml-jp-the-ocaml-japan-user-group/17998#post_1 Fri, 17 Apr 2026 12:31:10 +0000 discuss.ocaml.org-post-76166
[ANN] opam 2.5.1 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.

Try it!

The upgrade instructions are unchanged:

For Unix systems

bash -c "sh <(curl -fsSL https://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:

]]>
https://discuss.ocaml.org/t/ann-opam-2-5-1/17997#post_1 Thu, 16 Apr 2026 21:04:26 +0000 discuss.ocaml.org-post-76165
Emacs warning when opening OCaml file That fixed it! Thank you!

]]>
https://discuss.ocaml.org/t/emacs-warning-when-opening-ocaml-file/17996#post_3 Thu, 16 Apr 2026 14:48:22 +0000 discuss.ocaml.org-post-76164
Emacs warning when opening OCaml file yes, we recently change the name of the mode, I will patch ocaml.org soon as possible. You can follow this manual GitHub - tarides/ocaml-eglot: An overlay on Eglot for editing OCaml code using LSP · GitHub it is up to date.
Short answer, just replace ocaml-eglot by ocaml-eglot-mode :slight_smile:

]]>
https://discuss.ocaml.org/t/emacs-warning-when-opening-ocaml-file/17996#post_2 Thu, 16 Apr 2026 14:21:37 +0000 discuss.ocaml.org-post-76163