⚡ Algebraic Effects and Handlers

First-class computational effects with composable handlers

Overview

Algebraic effects are one of the most exciting developments in programming language theory. They separate the declaration of an effect (what can happen) from its interpretation (what it means), using handlers that intercept effects and can resume the suspended computation.

This module simulates algebraic effects on any OCaml version using a free monad / CPS encoding. OCaml 5 adds native effect handlers, but the concepts here apply universally.

Concepts Demonstrated

Effect Patterns

EffectOperationsHandler Provides
StateGet, PutThread mutable state through pure code
ExceptionRaiseError handling without unwinding
NondeterminismChoose, FailBacktracking search, collect all results
LoggingLogCollect messages, redirect output
AsyncAwait, ForkCooperative concurrency via scheduling

How It Works

(* Effects are declared as operations *)
type _ effect =
  | Get : int effect           (* read state *)
  | Put : int -> unit effect   (* write state *)

(* Code "performs" effects — doesn't know the implementation *)
let increment () =
  let x = perform Get in
  perform (Put (x + 1));
  x + 1

(* A handler gives meaning to effects *)
let run_state init computation =
  handle computation () with
  | Get, k    -> fun s -> continue k s s
  | Put s, k  -> fun _ -> continue k () s
  | return v  -> fun _ -> v
  |> fun f -> f init

(* Same code, different handler = different semantics *)
(* Handler for logging all state changes: *)
let run_logged computation =
  handle computation () with
  | Put s, k -> printf "State → %d\n" s; continue k ()
  | effect    -> forward effect  (* pass other effects through *)

Why Algebraic Effects?

Related Modules