Why Algebraic Effects Are Poised to Replace Monads in OCaml

There’s a quiet revolution happening in OCaml, and it doesn’t involve fancy new syntax or flashy language features. It’s about rethinking how we structure computations—and the solution might be the most elegant abstraction you’ve never heard of: algebraic effects.
I recently came across a fascinating blog post from Jane Street about their experience porting their Hardcaml_step_testbench library from monads to algebraic effects. The conclusion was striking: “most of what can be done with monads can be done with algebraic effects in a much more elegant way.”
That statement deserves serious attention, especially from developers who’ve spent years wrestling with monadic code.
The Core Insight

Monads have been the gold standard for modeling computation in functional programming for decades. Jane Street’s own Async library powers massive amounts of their infrastructure using monads. So why would one of the most sophisticated OCaml shops in the world decide to move away from them?
The answer lies in two fundamental problems that monads create, problems that most developers have simply learned to work around without questioning.
Problem 1: Monads infect everything.
Once you adopt a monad in your codebase, it spreads like digital kudzu. Every function that interacts with your monadic code must also become monadic. You need special versions of standard library functions—Deferred.List.iter instead of List.iter, for instance. You pepper your code with let%bind and return () statements. The original intent of your code gets buried under syntactic noise.
As the Jane Street post illustrates, compare this monadic code:
let send_numbers_to_server n =
let%bind txn = start_transaction () in
let%bind () = Deferred.for_ 0 ~to_:(n - 1) ~do_:(fun i ->
let%bind () = send_number txn i in
printf "Sent number %d\n" i;
return ())
in
let%bind result = wait_for_completion txn in
printf "Transaction done: %d!" result;
return ()
With what algebraic effects would allow:
let send_numbers_to_server (h : Deferred.Handler.t) n =
let txn = start_transaction h in
for 0 to n - 1 do
send_request h txn i;
printf "Sent number %d\n" i;
done;
let result = wait_for_completion h txn in
printf "Transaction done: %d!" result
The latter reads almost like imperative code. No special syntax. No return statements. The function returns a normal value that callers don’t need to treat specially.
Problem 2: Monads fight with modern OCaml features.
OCaml 5 introduced powerful new features like unboxed types and local modes—features that enable significant performance improvements. But there’s a catch: monads make these features nearly impossible to use.
The issue comes down to memory allocation. Monadic operations require globally allocated closures, while local modes and unboxed types specifically exist to keep values on the stack or avoid heap allocation entirely. These two worlds collide, and the compiler wins—meaning your performance-conscious code loses.
Algebraic effects solve this by shifting the “environment” management from the programmer’s closures to the language runtime. The runtime handles continuations, not your code. This seemingly simple shift opens the door to using all of OCaml 5’s modern features without compromise.
Why This Matters

This isn’t just academic. The implications ripple through practical software development in several ways.
Readability and maintainability. Code that’s easier to read is easier to maintain. The monad-infection problem means that adopting async IO or error handling in one part of your codebase often requires refactoring large swaths of related code. Algebraic effects could dramatically reduce this migration cost.
Performance. OCaml 5’s modes and unboxed types represent years of compiler work to bring better performance to functional programmers. Being able to use these features without sacrificing the benefits of effect handling is a big deal—especially for high-frequency trading systems like those at Jane Street.
Better stack traces. Anyone who’s debugged monadic code knows the pain of seeing “Failure: Monad.bind” in a stack trace with no useful context. Algebraic effects provide clearer, more actionable debugging information.
Composability. Try combining two monads together and you’ll quickly understand why this is a famous problem in functional programming. Effects offer more natural composability, allowing different effect handlers to work together without the exponential complexity of monad transformers.
Key Takeaways
Algebraic effects let you write code that looks normal while still having powerful effectful behavior underneath—unlike monads, which force their structure onto everything.
They’re not just for concurrency. Originally added to OCaml for parallel execution, algebraic effects have proven useful in domains like hardware simulation where they weren’t originally intended.
You don’t need to be a type theorist to use them. Jane Street’s Handled_effect library provides a typesafe API that lets developers reap benefits without understanding the underlying mechanics in depth.
The ecosystem is evolving. The library is currently being renamed from Oxcaml_effect to Handled_effect, indicating active development and refinement.
This is a practical shift, not a theoretical one. Jane Street ported real production code—a simulation library used for FPGA development—to prove the concept works at scale.
Looking Ahead
The story of algebraic effects in OCaml is still being written. While monads aren’t going anywhere overnight, we’re likely to see more libraries follow Jane Street’s lead in adopting effect-based APIs where they make sense.
What makes this particularly interesting is the pattern: a language feature (effects) designed for one purpose (concurrency) proves valuable in an entirely different domain (hardware simulation). This kind of cross-pollination often signals a fundamentally well-designed abstraction.
For developers working with OCaml or considering it, the message is clear: pay attention to algebraic effects. They might just be the elegant solution to problems you’ve been tolerating for years.
Based on analysis of “Fun with Algebraic Effects – from Toy Examples to Hardcaml Simulations” from Jane Street Blog