Cofree Comonad
Tutorial Video
Text description (accessibility)
This video demonstrates the "Cofree Comonad" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. The Cofree comonad is the categorical dual of the Free monad. Key difference from OCaml: | Aspect | Rust | OCaml |
Tutorial
The Problem
The Cofree comonad is the categorical dual of the Free monad. Where Free builds up effects lazily for later interpretation, Cofree builds up a potentially infinite tree of values annotated with a functor at every node. It is the universal comonad: every comonad arises as a coalgebra for some Cofree instance. In Rust, Cofree enables elegant tree-shaped data structures where each node carries both a value and a collection of children described by a functor.
🎯 Learning Outcomes
Cofree f a = (a, f (Cofree f a))extract and extend for CofreeCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
| Aspect | Rust | OCaml |
|---|---|---|
| Recursion breaking | Box<Cofree<A>> | Lazy.t list |
| Infinite structures | requires Rc/arena tricks | natural with Lazy.t |
| extend cloning | requires A: Clone + 'static | no explicit bounds |
| Functor parameter | baked in as Vec | polymorphic over list functor |
| Coinduction | not native | codata via laziness |
A fully generic Cofree<F, A> in Rust requires HKT simulation (GATs), making the Vec-specialized version far more practical for most use cases.
OCaml Approach
OCaml's lazy evaluation makes Cofree natural for infinite structures:
type ('f, 'a) cofree = Cofree of 'a * ('f, 'a) cofree list Lazy.t
let extract (Cofree (a, _)) = a
let rec extend f tree =
let (Cofree (_, children)) = tree in
Cofree (f tree, lazy (List.map (extend f) (Lazy.force children)))
(* Infinite stream as Cofree over unit functor *)
let rec nats n = Cofree (n, lazy [nats (n + 1)])
OCaml's Lazy.t avoids the need for explicit Box and enables genuinely infinite Cofree structures without stack overflow.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Cofree 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
Option as the functor (making it a potentially-terminated stream).extend to implement a Huffman encoding annotator: label each node with its subtree character frequency.unfold: S -> (A, Vec<S>) -> Cofree<A> as the Cofree anamorphism (corecursive unfold).duplicate (the Cofree version of extend id) produces a tree where each node's annotation is the subtree rooted there.extend to compute the attributes in one traversal.