Introduction to Algebraic Effects
Tutorial Video
Text description (accessibility)
This video demonstrates the "Introduction to Algebraic Effects" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. Algebraic effects are a modern alternative to monads for structuring side effects. Key difference from OCaml: 1. **Native vs. simulated**: OCaml 5 has native effect handlers with efficient stack manipulation; Rust requires explicit continuation
Tutorial
The Problem
Algebraic effects are a modern alternative to monads for structuring side effects. Unlike free monads (which build heap-allocated trees), algebraic effects are handled at the runtime level — the effect is "thrown" and a handler "catches" it, potentially resuming the computation. OCaml 5 introduced native effect handlers. Rust simulates them using closures and callbacks. Effects are used in async runtimes (every await is an effect), error handling, non-determinism, and resource management.
🎯 Learning Outcomes
Code Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
continue k can call k multiple times (non-determinism); Rust's FnOnce callbacks can only be called once.OCaml Approach
OCaml 5's native effect handlers:
effect Read : string
let with_reader env program =
match_with program ()
{ retc = (fun v -> v)
; exnc = raise
; effc = fun (type a) (eff : a eff) ->
match eff with
| Read -> Some (fun (k : (a, _) continuation) ->
continue k env)
| _ -> None }
The handler intercepts Read effects, provides a value, and resumes the computation via continue k env. This is purely functional with no heap-allocated trees — the runtime manages the stack frames.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Effect Intro
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
with_logger handler that intercepts Log(message) effects and stores them in a Vec<String>.Amb(choices: Vec<A>) effect that a handler interprets by trying all choices.