Futumorphism
Tutorial Video
Text description (accessibility)
This video demonstrates the "Futumorphism" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. A futumorphism (futu) is the dual of a histomorphism — an anamorphism that can look ahead multiple levels into the future structure being built. Key difference from OCaml: 1. **HKT requirement**: These morphisms ideally require higher
Tutorial
The Problem
A futumorphism (futu) is the dual of a histomorphism — an anamorphism that can look ahead multiple levels into the future structure being built. It uses a free monad of the base functor as the coalgebra target, allowing the generator to produce multiple levels of structure at once. This is useful for expanding macros, generating tree structures, and producing ahead-of-need outputs.
🎯 Learning Outcomes
Code Example
#![allow(clippy::all)]
//! # Futumorphism
//! Unfold that can produce multiple layers at once.
pub fn futu<S, A>(seed: S, step: impl Fn(S) -> FutuStep<A, S>) -> Vec<A> {
let mut result = Vec::new();
let mut s = seed;
loop {
match step(s) {
FutuStep::Done => break,
FutuStep::One(a, next) => {
result.push(a);
s = next;
}
FutuStep::Two(a, b, next) => {
result.push(a);
result.push(b);
s = next;
}
}
}
result
}
pub enum FutuStep<A, S> {
Done,
One(A, S),
Two(A, A, S),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_futu() {
let xs = futu(0, |n| {
if n >= 4 {
FutuStep::Done
} else {
FutuStep::One(n, n + 1)
}
});
assert_eq!(xs, vec![0, 1, 2, 3]);
}
}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)]
//! # Futumorphism
//! Unfold that can produce multiple layers at once.
pub fn futu<S, A>(seed: S, step: impl Fn(S) -> FutuStep<A, S>) -> Vec<A> {
let mut result = Vec::new();
let mut s = seed;
loop {
match step(s) {
FutuStep::Done => break,
FutuStep::One(a, next) => {
result.push(a);
s = next;
}
FutuStep::Two(a, b, next) => {
result.push(a);
result.push(b);
s = next;
}
}
}
result
}
pub enum FutuStep<A, S> {
Done,
One(A, S),
Two(A, A, S),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_futu() {
let xs = futu(0, |n| {
if n >= 4 {
FutuStep::Done
} else {
FutuStep::One(n, n + 1)
}
});
assert_eq!(xs, vec![0, 1, 2, 3]);
}
}#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_futu() {
let xs = futu(0, |n| {
if n >= 4 {
FutuStep::Done
} else {
FutuStep::One(n, n + 1)
}
});
assert_eq!(xs, vec![0, 1, 2, 3]);
}
}
Deep Comparison
Futumorphism
Unfold producing multiple layers