Effects as Exceptions
Tutorial Video
Text description (accessibility)
This video demonstrates the "Effects as Exceptions" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. Exceptions are a special case of algebraic effects — an effect that does not resume the computation. Key difference from OCaml: 1. **Typing**: Rust's `Result<T, E>` is statically typed — the error type is part of the function signature; OCaml's `exn` is a single open extensible type (all exceptions have the same type).
Tutorial
The Problem
Exceptions are a special case of algebraic effects — an effect that does not resume the computation. When an exception is thrown, the stack is unwound to the nearest handler, which may handle the exception and continue or re-throw it. Understanding exceptions as non-resumable effects unifies the conceptual model: both exceptions and effects interrupt the normal control flow and transfer control to a handler.
🎯 Learning Outcomes
Result<T, E> and the ? operator implement exception-like error handling in RustAbort results and exception propagationResult) with OCaml's dynamic exceptions (exn)Code Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
Result<T, E> is statically typed — the error type is part of the function signature; OCaml's exn is a single open extensible type (all exceptions have the same type).? compiles to conditional branches — no runtime overhead on the happy path; OCaml's exceptions use stack unwinding — no overhead until thrown.? requires the error types to match (or implement From); OCaml's exceptions propagate to any matching handler regardless of type.Result explicitly; OCaml's exceptions can propagate silently — closer to Java's unchecked exceptions.OCaml Approach
OCaml has two exception mechanisms:
exception MyError of string; raise (MyError "msg") — caught with try ... with MyError msg -> ...effect Fail : string — caught with a handler that does not call continueThe traditional OCaml approach uses dynamic exceptions (like Java's unchecked exceptions). OCaml's result type provides checked, typed exceptions similar to Rust's Result.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Effect Exceptions
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
Vec<E> — collect all errors rather than stopping at the first.try_all<T, E>(ops: Vec<impl FnOnce() -> Result<T, E>>) -> Result<Vec<T>, Vec<E>> that runs all operations and returns all successes or all errors.retry<T, E>(n: usize, f: impl FnMut() -> Result<T, E>) -> Result<T, E>.