Puzzles and extended exercises#

A graded problem collection. Every puzzle here follows the same protocol, and it is the whole point of this chapter: commit to a prediction before you run anything. Write your answer on paper — the normal form, the step count, the yes/no, the type — and only then open the lab and check. A puzzle you merely read is a puzzle wasted; the λ-calculus is small enough that your errors are always interesting, and the engine will tell you exactly where your mental substitution went wrong.

Difficulty is marked ★ (a minute), ★★ (a good think), ★★★ (bring coffee). Solutions hide in dropdown boxes; every output inside them was produced by the real engine, step counts included.

Ground rules

Five conventions used throughout, all checkable in the lab itself:

  • constants — the named library (TRUE, PLUS, LEQ, Y, …) every puzzle may use freely

  • let NAME = <term> — session-local definitions; recipes below assume you paste their let lines in order, in one session

  • decode <term> — normalizes and reads the result back as a numeral/boolean; our favourite oracle

  • equiv <t> = <u> — β-convertibility via normal forms (no η!); alpha is the strict renaming-only cousin

  • help <command> — every command explains itself with examples when in doubt

Warm-ups ★#

Five finger exercises. For each: predict the output and, where a step count is printed, the number of β-steps.

W1. What is the normal form of (λx. x x) (λy. y), and in how many steps? nf (\x. x x) (\y. y)

W2. A Church numeral is a function — so apply one to another. What number is 2 2? What about 3 2 and 2 3? (Careful: it is not symmetric, and it is not multiplication.) decode 2 2

W3. A numeral iterates. What is 3 SUCC 4 — the numeral 3 used as a loop, body SUCC, seed 4? decode 3 SUCC 4

W4. TRUE is a projection wearing a costume. Predict the normal form of (λx. λy. x) A B where A, B are free variables. nf (\x. \y. x) A B

W5. Subtraction, but the answer would be negative. What does the lab say — and how does it say it? decode SUB 2 5

Binding puzzles ★★#

Names are scaffolding; binding structure is the building. These puzzles are about seeing through the scaffolding — with alpha (strict α-equivalence, no β), debruijn (the nameless view), and one deliberate trap that the engine defuses in front of you.

B1. The shadowing trap. Consider λx. λx. x. Which x does the body see? Decide whether it is α-equivalent to λx. λy. y, then to λx. λy. x, and check both. Then look at its De Bruijn form. alpha \x. \x. x = \x. \y. y

alpha \x. \x. x = \x. \y. x
debruijn \x. \x. x

B2. Swapped names, same term? Are λx. λy. x y and λy. λx. y x α-equivalent? (Do not let the letter swap hypnotize you — trace which binder each variable points to.) alpha \x. \y. x y = \y. \x. y x

B3. Nameless S. Write down, by hand, the De Bruijn form of the S combinator λx. λy. λz. x z (y z). Then check. debruijn \x. \y. \z. x z (y z)

B4. The capture trap. Reduce (λx. λy. x) y — where the argument y is free. Naive textual substitution would produce λy. y, the identity. That answer is wrong: it captures the free y. Predict what the engine does instead, then watch it. reduce (\x. \y. x) y

equiv (\x. \y. x) y = \z. y
equiv (\x. \y. x) y = \y. y

B5. Three notions of “the same”. Take λx. f x and the bare f. Are they the same term? You have three judges: alpha (renaming only), equiv (β-normal forms, no η), and eta. Predict each verdict before you poll them. alpha \x. f x = f

equiv \x. f x = f
eta \x. f x

Encoding puzzles ★★#

Now you build. Each recipe is a fresh session: paste the let lines in order, then interrogate your creation. defs lists what you have defined; undef NAME removes a mistake.

E1. MAX and MIN from LEQ and IF#

Define binary maximum and minimum of Church numerals using only the library’s LEQ and IF. Then convince yourself with a slick one-liner that for any pair, MIN and MAX together preserve the sum.

let MAX = \m. \n. IF (LEQ m n) n m

let MIN = \m. \n. IF (LEQ m n) m n
decode MAX 3 5
decode MAX 5 3
decode MIN 4 2
decode MAX 3 3
equiv PLUS (MIN 4 2) (MAX 4 2) = PLUS 4 2

Why does reduce stop “before the end” on this one?

If you watch the conservation check with reduce PLUS (MIN 4 2) (MAX 4 2), the trace halts after 60 steps saying “the displayed term is partial”. Nothing is stuck — the term reaches its normal form in 76 β-steps (nf confirms: = 6); reduce simply caps its step-by-step display at 60 lines, because it is a chalkboard, not a calculator.

Where do 76 steps go for such a tiny computation? Measured piece by piece: branch selection is cheap (IF TRUE 4 2 — 5 steps), but the boolean is not: each Kleene predecessor rebuilds its numeral (PRED 4 — 13 steps), SUB 4 2 applies it twice (28), so one LEQ costs 28 and each of MIN 4 2/MAX 4 2 costs 35 — and the conservation law runs both before PLUS even starts. Meanwhile the discarded branch of every IF vanishes unevaluated — normal order is lazy; the whole price is in deciding, never in the road not taken.

And reduce MIN 4 2 on its own fits comfortably — 35 steps — with a finale worth watching: around step 32 the whole LEQ computation collapses into a literal selector, and the last four lines read

  →β      (λt. (λf. f)) (λf'. (λx. f' (f' (f' (f' x))))) (λf''. (λx'. f'' (f'' x')))
  →β      (λf. f) (λf'. (λx. f' (f' x)))
  →β      λf x. f (f x)
  β-normal form reached in 35 step(s).   = 2  (Church numeral)

FALSE appears as a term, swallows the numeral 4 without ever evaluating it, and hands back 2. The endpoint λf x. f (f x) is the numeral 2church 2 prints the identical term. (Meanwhile alpha MIN 4 2 = 2 says ≢α — strict α never computes — while equiv agrees they are β-equal: the two judgments in one example.)

Rules of thumb: reduce to watch mechanics whenever the count fits the 60-line window; nf/decode/equiv for answers (1,000-step budget). And if MIN ever comes back as a stuck free variable in nf MIN 4 2 MIN (0 steps), your page was reloaded — let definitions live only in the session; run the let lines again (defs shows what survived).


### E2. NOR from NOT and OR — and a lucky strike

Define `MYNOR p q = NOT (OR p q)`, verify all four rows of its truth table, and then try
something bolder: is your term β-convertible to the library's `NOR` — not just pointwise equal,
but *as a function*?

[`let MYNOR = \p. \q. NOT (OR p q)`](https://bnaskrecki.faculty.wmi.amu.edu.pl/lab-lambda/?cmd=let%20MYNOR%20%3D%20%5Cp.%20%5Cq.%20NOT%20%28OR%20p%20q%29)

```text
decode MYNOR FALSE FALSE
decode MYNOR FALSE TRUE
decode MYNOR TRUE FALSE
decode MYNOR TRUE TRUE
equiv MYNOR = NOR

E3. IMPLIES from NAND alone#

NAND is functionally complete, so implication must be buildable from it and nothing else. Recall p → q ≡ ¬p ∨ q ≡ NAND(p, ¬q), and ¬q ≡ NAND(q, q). Define it, verify the full truth table — and then ask the dangerous question: equiv MYIMP = IMPLIES?

let MYIMP = \p. \q. NAND p (NAND q q)

decode MYIMP TRUE TRUE
decode MYIMP TRUE FALSE
decode MYIMP FALSE TRUE
decode MYIMP FALSE FALSE
equiv MYIMP TRUE FALSE = IMPLIES TRUE FALSE
equiv MYIMP = IMPLIES

E4. Three-way XOR#

Define XOR3 p q r by folding the library’s binary XOR. Then answer before running: what is XOR3 TRUE TRUE TRUE? (If your instinct says FALSE because “they’re all equal”, this puzzle was built for you.)

let XOR3 = \p. \q. \r. XOR p (XOR q r)

decode XOR3 TRUE TRUE TRUE
decode XOR3 TRUE TRUE FALSE
decode XOR3 TRUE FALSE FALSE
decode XOR3 TRUE FALSE TRUE
decode XOR3 FALSE FALSE FALSE

Numeral puzzles ★★#

Arithmetic on Church numerals is full of small scandals. Three of the best:

N1. Zero to the zero. The library’s POW is λm n f x. n m f x — exponentiation is literally “apply n to m” (warm-up W2!). So what is POW 0 0? Predict, then run — and count the steps. nf POW 0 0

N2. The monus surprise. Is PRED (SUCC n) = n for every numeral n? And symmetrically — is SUCC (PRED n) = n? Find a counterexample to one of them or argue there is none. equiv PRED (SUCC 7) = 7

equiv PRED (SUCC 0) = 0
equiv SUCC (PRED 0) = 0

N3. Parity in four symbols. A numeral n is an iterator; NOT is an involution. So what does n NOT TRUE compute? Test your claim on 0, 6, 7, then wrap it as a definition. decode 6 NOT TRUE

decode 7 NOT TRUE
decode 0 NOT TRUE
let EVEN = \n. n NOT TRUE
decode EVEN 10
decode EVEN 9

Typed puzzles ★★#

Switch engines: ch term runs principal-type inference (Algorithm W) on untyped terms, and ch type searches for inhabitants of implicational formulas — provability in intuitionistic logic, live. The game: write the type before the machine does.

T1. Four famous combinators. Infer, by hand, the principal types of

\[ \mathsf{B} = \lambda f\, g\, x.\, f\,(g\,x) \qquad \mathsf{C} = \lambda f\, x\, y.\, f\,y\,x \qquad \mathsf{W} = \lambda f\, x.\, f\,x\,x \qquad \mathsf{pair} = \lambda a\, b\, f.\, f\,a\,b \]

then check each: ch term \f. \g. \x. f (g x)

ch term \f. \x. \y. f y x
ch term \f. \x. f x x
ch term \a. \b. \f. f a b

T2. The one that got away. W duplicates its argument and is perfectly typable. So why does ch term \x. x x fail? Predict the error message’s shape before you look.

T3. Tautology or not? Read each closed type below as a propositional formula. Decide — by logic alone — which are intuitionistic tautologies, then let the inhabitation search vote:

The prove ladder ★★→★★★#

The prove command is the lab’s interactive Curry–Howard proof builder: state an implicational proposition, close it tactic by tactic (intro, apply, exact, assumption…), and watch the proof term grow hole by hole (?₀, ?₁, …). Five rungs, strictly increasing. If you get stuck mid-proof, hint asks the built-in proof search for the next move, and undo retracts a step — but try to climb bare-handed first. qed extracts your λ-term and its principal type.

Research-grade finale ★★★ — trees that fold themselves#

Church numerals encode “iterate n times”. The same idea — a data structure is its own recursor — encodes any algebraic datatype. A binary tree with numeral-labelled leaves becomes a function of two arguments: what to do at a leaf, and how to combine two folded subtrees:

\[ \mathrm{LEAF}\;n \;=\; \lambda l\,b.\; l\,n \qquad\qquad \mathrm{BRANCH}\;t\,u \;=\; \lambda l\,b.\; b\;(t\,l\,b)\;(u\,l\,b) \]

Every “recursive” function on trees is then a single application — no Y combinator, no general recursion, ever. Build the kit in one session:

let LEAF = \n. \l. \b. l n

let BRANCH = \t. \u. \l. \b. b (t l b) (u l b)
let T1 = BRANCH (LEAF 1) (BRANCH (LEAF 2) (LEAF 3))
let SUMTREE = \t. t (\n. n) PLUS
let LEAVES = \t. t (\n. 1) PLUS
let MAX = \m. \n. IF (LEQ m n) n m
let DEPTH = \t. t (\n. 1) (\a. \c. SUCC (MAX a c))

Now the puzzles:

  1. Predict SUMTREE T1, LEAVES T1, DEPTH T1 — then decode all three.

  2. Define T2 = BRANCH T1 (BRANCH T1 (LEAF 10)) and predict all three again before running.

  3. Mirror. Define a function reflecting a tree left↔right, as a fold that rebuilds the tree. Check that mirroring changes T1 but that mirroring twice is the identity — as an honest equiv between λ-terms, not just as matching sums.

  4. Type the constructors. What does ch term make of LEAF and BRANCH? Can you recognize the fold in the type?

Where this connects

The puzzles above are the lab-side shadows of the lectures:

  • Lecture 2 — λ-calculus — α/β/η, capture-avoiding substitution, De Bruijn indices, and the Church encodings behind W1–N3

  • Lecture 1 — type theory — principal types, Algorithm W, and the inhabitation questions of T1–T3

  • Lecture 3 — propositional logic — the intuitionistic/classical divide that makes T3 and the prove ladder tick

  • Lecture 4 — Lean — every ch type witness ships with a one-click Live Lean theorem; the finale’s fold is the ancestor of Lean’s inductive types

  • Cheatsheet — the whole command surface on one page, for when a puzzle sends you hunting