Comonad Laws
Tutorial Video
Text description (accessibility)
This video demonstrates the "Comonad Laws" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. Just as monads must satisfy left identity, right identity, and associativity, comonads must satisfy three dual laws. Key difference from OCaml: | Aspect | Rust | OCaml |
Tutorial
The Problem
Just as monads must satisfy left identity, right identity, and associativity, comonads must satisfy three dual laws. These laws ensure that extract and extend compose predictably, making comonadic abstractions composable and refactorable without hidden surprises. This example formalizes and verifies the comonad laws in Rust using property-based tests on concrete comonad instances.
🎯 Learning Outcomes
extend implementation violates a lawCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
| Aspect | Rust | OCaml |
|---|---|---|
| Law encoding | unit tests + generics | module signature + qcheck |
| Trait object limits | impl Fn not object-safe | first-class polymorphism |
| Verification | compile-time + runtime | mostly runtime via qcheck |
PartialEq constraint | required for equality tests | structural equality built in |
| Laws as types | not enforceable | not enforceable (same limitation) |
Neither language can enforce comonad laws at the type level — they remain runtime-verifiable contracts. This mirrors the situation with monad laws.
OCaml Approach
In OCaml the laws are typically stated as signatures in a functor:
module type COMONAD = sig
type 'a t
val extract : 'a t -> 'a
val extend : ('a t -> 'b) -> 'a t -> 'b t
(* Laws (as comments, verified by quickcheck) *)
(* extend extract = Fun.id *)
(* extract (extend f x) = f x *)
(* extend f (extend g x) = extend (fun y -> f (extend g y)) x *)
end
QuickCheck/qcheck handles property verification; Rust uses proptest or hand-written loops.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Comonad Laws
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
Store<usize, i32> comonad using a fixed finite array as the getter.extend-like operation that satisfies laws 1 and 2 but not 3 (associativity); explain which law breaks and why.Identity<i32> with random values.duplicate defined as extend id always satisfies the comonad laws if extend does.ComonadLaws<W> trait with associated functions that check all three laws given a sample value, and implement it for both Identity and Env.