Every Cantor function body is exactly one combinator application. There are five combinators in total:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/felipenugo/cantor-interpreter/llms.txt
Use this file to discover all available pages before exploring further.
comp and pair are available in every program; compair and primrec require extended mode; mu is available in all modes but introduces the possibility of non-termination. This page covers each combinator in detail with real examples drawn from the test suite.
comp — function composition
Syntaxx, comp f g evaluates g first, then passes the result to f:
comp is the primary tool for chaining functions together. It directly mirrors mathematical function composition.
When to use it
Use comp whenever you need to apply one function to the result of another. Because every Cantor combinator operates on a single number, comp is needed any time you want to post-process the output of a helper.
Example — computing the predecessor
From tests/programs/phase1-core/anterior.cantor:
anterior(5):
aparella_amb_1(5)→pair id k_1→<5.1>(Cantor-encoded)diff(<5.1>)→max(0, 5 − 1)→4
anterior(0):
aparella_amb_1(0)→<0.1>diff(<0.1>)→max(0, 0 − 1)→0
pair — Cantor-encode two results
Syntaxx, pair f g applies both f and g to the same x and encodes their results as a single natural number using the Cantor pairing function:
π(a, b) = ((a + b) × (a + b + 1)) / 2 + b.
When to use it
pair is the fundamental way to pass two values to a function that expects a single encoded pair. For example, built-ins add, mul, and diff all decode their input with fst/snd, so you must first construct a pair before calling them on two computed values.
Example — pairing identity with a constant
aparella_amb_1(7):
id(7)→7k_1(7)→1pair id k_1→π(7, 1)→<7.1>→36
diff, add, mul, or any other function that expects <x.y>.
compair — compose after pairing (extended only)
Syntaxcompair f g h is syntactic sugar for comp f (pair g h). Given input x:
g(x) and h(x), pairs them, and passes the result to f.
When to use it
compair replaces the common two-step pattern of first defining a pair helper and then composing with comp. It keeps definitions concise whenever you need to pass two derived values to a binary function.
Example — quotient search in div.cantor
From tests/programs/phase4-minimization/div.cantor:
q1 illustrates compair directly: given the encoded input z = <<x.y>.q>, it computes snd(z) = q and k_1(z) = 1, then passes <q.1> to add, yielding q + 1.
Without compair the equivalent definition would need an intermediate pair function:
mu — minimization (unbounded search)
Syntaxx, mu f searches for the smallest natural number k ≥ 0 such that f(<x.k>) ≠ 0, and returns that k:
k = 0, 1, 2, … in order, calling f(π(x, k)) each time, and stops as soon as the result is non-zero.
When to use it
mu expresses any search whose stopping condition can be computed as a Cantor function. Classical uses include integer division, modulo, and any inverse function. Combined with the rest of the language, mu makes Cantor Turing-complete.
Example — integer division by linear search
From tests/programs/phase4-minimization/div.cantor (shown in full above), the key definition is:
div is the Cantor encoding of <x.y> (dividend and divisor). The predicate test_quotient returns non-zero when y × (q + 1) > x, i.e., when q has exceeded the true quotient. The smallest such k is the integer quotient ⌊x / y⌋.
primrec — primitive recursion (extended only)
Syntaxprimrec f g h iterates from 0 to x (inclusive), accumulating a result. At each step i:
- If
f(i) ≠ 0(base case):current_result = g(i) - Otherwise (recursive step):
current_result = h(<i.previous_results>)
previous_results is the Cantor-encoded history of all prior current_result values, accumulated as <last.<second_last.<…>>>.
After the loop completes (at i = x), the function returns current_result.
primrec is the structured alternative to mu for functions whose recursion depth is exactly x. It is suited to definitions like factorial, Fibonacci, and summation, where the recurrence is known in advance. Unlike mu, it always terminates (the loop runs exactly x + 1 times).
Example — factorial
From tests/programs/phase5-primrec/factorial.cantor:
is_base checks whether the current index i equals 0. When it does, g = k_1 returns 1 (0! = 1). On subsequent steps, h = step computes i × previous_result via compair mul fst segon: fst extracts i from <i.previous_results> and segon (comp fst snd) extracts the immediately preceding result.
factorial(4) trace:
| i | f(i) ≠ 0? | current_result | previous_results |
|---|---|---|---|
| 0 | yes (base) | k_1(0) = 1 | <1.0> |
| 1 | no | step(<1.<1.0>>) = 1×1 = 1 | <1.<1.0>> |
| 2 | no | step(<2.<1.<1.0>>>) = 2×1 = 2 | <2.<1.<1.0>>> |
| 3 | no | step(<3.<2.<…>>>) = 3×2 = 6 | <6.<2.<…>>> |
| 4 | no | step(<4.<6.<…>>>) = 4×6 = 24 | — |
24. ✓