Environment Comonad
Tutorial Video
Text description (accessibility)
This video demonstrates the "Environment Comonad" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. The Environment comonad (also called the Reader comonad's dual, or Co-Reader) pairs a value with a fixed environment: `(e, a)`. Key difference from OCaml: | Aspect | Rust | OCaml |
Tutorial
The Problem
The Environment comonad (also called the Reader comonad's dual, or Co-Reader) pairs a value with a fixed environment: (e, a). You can always extract the value, ask what the environment is, and extend computations that depend on both the current value and the surrounding environment. This models read-only context propagation where each step in a computation can inspect a shared environment without passing it explicitly.
🎯 Learning Outcomes
extract, extend, and duplicate for the Env comonadask retrieves the environment and local modifies itCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
| Aspect | Rust | OCaml |
|---|---|---|
| Environment sharing | E: Clone on each operation | implicit GC sharing |
| Local transformation | returns Env<E2, A> (new type) | returns same env type |
| Duplicate | requires A: Clone | structural copy |
| Composition | .extend(f).extend(g) chains | same, pipe-friendly |
| Adjunction | dual to State monad | same theoretical dual |
The Env comonad is adjoint to the State monad: Env extracts a value from context while State injects a state into continuation. Together they form the (- × e) ⊣ (e →) adjunction.
OCaml Approach
OCaml represents Env as a plain pair:
type ('e, 'a) env = { env: 'e; val_: 'a }
let extract { val_; _ } = val_
let ask { env; _ } = env
let extend f w = { env = w.env; val_ = f w }
let duplicate w = { env = w.env; val_ = w }
let local f w = { env = f w.env; val_ = w.val_ }
OCaml's implicit polymorphism avoids the Clone constraints Rust requires. The tradeoff is that OCaml's type inference handles the variance silently while Rust makes it explicit.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Env Comonad
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
fmap for Env<E, A> that maps the value while keeping the environment unchanged.extend extract = id, extract . extend f = f, extend f . extend g = extend (f . extend g).Env<AppConfig, Service> where each extend step configures a new service layer.asks: given a function E -> B, produce Env<E, B> — the comonadic equivalent of Reader's asks.unit and counit of the adjunction and checking the triangle identities.