§ Overview
The runtime treats recursion as the primary control flow primitive. Iteration is a special case of a tail call. Memory is a special case of a stream. Time is a special case of a lazy fold over an unbounded sequence.
The core API exposes a small set of combinators that compose into arbitrarily complex recursive structures without stack growth. Implementations are verified at compile time using a dependent type checker that has its own dedicated chapter.
§ Installation
Three supported channels: stable, edge, and proof-carrying. The stable channel is recommended for production deployments.
1$ curl -fsSL https://muhan.dev/install.sh | sh2$ muhan init --scale=infinite --strict3# resolves the project graph in O(log n) ammortized4$ muhan verify
§ Fixed Points
A fixed point of f is any x such that f(x) = x. The standard library exposes fix, the least fixed-point combinator over a bottom-pointed lattice.
The supremum is computed lazily; in practice the runtime stops at the first index where two successive iterates are bisimilar under the chosen equivalence.
1import { fix, memo } from "@muhan/core";23// classic factorial as the fixed point of an open recursion.4const factorial = fix(self => (n: bigint): bigint =>5 n <= 1n ? 1n : n * self(n - 1n)6);78const fib = memo(fix(self => (n: bigint): bigint =>9 n < 2n ? n : self(n - 1n) + self(n - 2n)10));1112factorial(42n); // 1405006117752879898543142606244511569936384000000000n13fib(10000n); // computed in 11 ms with memoization
§ Lazy Streams
Streams are codata: corecursively defined, observed by demand. The standard library models the natural numbers, the primes, and the digits of π as ordinary stream values.
1import { stream } from "@muhan/core";23const naturals = stream.iterate(2n, n => n + 1n);45const sieve = (s) => s.unfold(({ head, rest }) => ({6 value: head,7 next: sieve(rest.filter(x => x % head !== 0n))8}));910const primes = sieve(naturals);11primes.take(10); // [2,3,5,7,11,13,17,19,23,29]
1import { cf } from "@muhan/numerics";23// continued-fraction expansion of pi.4const pi = cf.brouncker();56pi.digits(12);7// "3.141592653589"89pi.precision(10_000)10 .at(9999); // 7
§ Algorithm Visualisation
Each documentation page can embed live algorithm visualisations. The block below traces a depth-first walk of a recursive call tree as it unfolds.
§ Reference Tables
Selected combinators from @muhan/core. Full reference under reference/api.md.
fixmemostreamtrampolineunfold§ Recent Changes
-
added
stream.zipLazyfor non-aligned codata. v8.∞.0 - fixed memoisation table now releases under bisimilarity equivalence. v8.7.4
-
break
fixno longer accepts thunks; usedelay. v8.7.0 -
added
cantor-set generator under
numerics/cantor. v8.6.2