Hylomorphism
Tutorial Video
Text description (accessibility)
This video demonstrates the "Hylomorphism" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. A hylomorphism (hylo) composes an anamorphism followed by a catamorphism — build then fold. Key difference from OCaml: 1. **HKT requirement**: These morphisms ideally require higher
Tutorial
The Problem
A hylomorphism (hylo) composes an anamorphism followed by a catamorphism — build then fold. This is the general recursive scheme: any recursive computation that builds an intermediate structure and then folds it is a hylomorphism. Mergesort is the canonical example: unfold the list into a tree of comparison results, then fold to produce the sorted list.
🎯 Learning Outcomes
Code Example
#![allow(clippy::all)]
//! # Hylomorphism
//! Unfold then fold - ana composed with cata.
pub fn hylo<S, A, B>(
seed: S,
next: impl Fn(S) -> Option<(A, S)>,
nil: B,
cons: impl Fn(A, B) -> B,
) -> B {
let list: Vec<A> = {
let mut result = Vec::new();
let mut s = seed;
while let Some((a, s2)) = next(s) {
result.push(a);
s = s2;
}
result
};
list.into_iter().rev().fold(nil, |acc, x| cons(x, acc))
}
pub fn factorial(n: u64) -> u64 {
hylo(
n,
|k| if k == 0 { None } else { Some((k, k - 1)) },
1,
|x, acc| x * acc,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factorial() {
assert_eq!(factorial(5), 120);
}
}Key Differences
recursion-schemes are widely used; in Rust and OCaml, direct recursion is more common in practice.OCaml Approach
OCaml's pattern matching and recursive types make morphism implementations natural. The Fix type and F-algebra/coalgebra patterns translate directly, though without Haskell's typeclass machinery:
(* OCaml recursive schemes use:
- Recursive variant types for F-algebras
- Higher-order functions for the morphism
- GADTs for type-safe fixed points in advanced cases *)
Full Source
#![allow(clippy::all)]
//! # Hylomorphism
//! Unfold then fold - ana composed with cata.
pub fn hylo<S, A, B>(
seed: S,
next: impl Fn(S) -> Option<(A, S)>,
nil: B,
cons: impl Fn(A, B) -> B,
) -> B {
let list: Vec<A> = {
let mut result = Vec::new();
let mut s = seed;
while let Some((a, s2)) = next(s) {
result.push(a);
s = s2;
}
result
};
list.into_iter().rev().fold(nil, |acc, x| cons(x, acc))
}
pub fn factorial(n: u64) -> u64 {
hylo(
n,
|k| if k == 0 { None } else { Some((k, k - 1)) },
1,
|x, acc| x * acc,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factorial() {
assert_eq!(factorial(5), 120);
}
}#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factorial() {
assert_eq!(factorial(5), 120);
}
}
Deep Comparison
Hylomorphism
Compose unfold with fold