PURPOSE: Answers to the exercises found in Combinator Engine
Exercise 1: To prove:
S K K x = x S K K x = K x { K x } = x
Exercise 2:
To prove:
B f g x = S { K S } K f g x = f { g x } S { K S } K f g x = K S f { K f } g x = S { K f } g x = K f x { g x } = f { g x }
To prove:
C f x y = S { B B S } { K K } x y = f y x S { B B S } { K K } f x y = B B S f { K K f } x y = B { S f { K K f } } x y = S f { K K f x } y = f y { K K f x y } = f y { K x y } = f y x
To prove:
T x f = C I x f = f x C I x f = I f x = f x
To prove:
W f x = C S I f x = f x x C S I f x = S f I x = f x { I x } = f x x
To prove:
M x = S I I x = x x S I I x = I x { I x } = x { I x } = x x
Exercise 3:
To prove:
S { K p } = B p S { K p } x y = K p y { x y } = p { x y } = B p x y ⌷
To prove:
B p { K q } = K { p q } B p { K q } x = p { K q x } = p q = K { p q } x ⌷
To prove:
B p I = p B p I x = p { I x } = p x
To prove:
S p I = W p S p I x = p x { I x } = p x x = W p x
To prove:
S p {K q} = C p q S p {K q} x = p x {K q x} = p x q = C p q x
The remaining two identities were already proven in exercise 2.
Exercise 4. Explain why
n { K false } true
tests for zero.
n { K false } true
is true if n is zero. Otherwise, it's
K false { K false { ... true } ... } \------ ------/ \/ n times
But, since
K false x = false
for all x, the result is false.
Exercise 5. We want to compare two Church numerals to see if one is greater than the other.
One possible solution is to use Kleene's trick of making downward-counting lists, starting from both numbers. We can then iterate through the two lists in parallel. The one that hits zero first is the smaller.
# Determine which list hits zero first, retirn false if it's the first and # true if it's the second. set lgrtr [lambda lgrtr [lambda list1 [lambda list2 { zero? { hd list1 } false { zero? { hd list2 } true { lgrtr { tl list1 } { tl list2 } } } }]]] puts "lgrtr = $lgrtr" macro lgrtr $lgrtr # Determine which of two Church numerals is the greater by iterating through # countdown lists set grtr [lambda m [lambda n { Y lgrtr { downFrom m } { downFrom n } }]] puts "grtr = $grtr" macro > $grtr
Exercise 6. We want to find the greatest common divisor of two Church numerals.
We use Euclid's algorithm, and compute the remainder of division by repeated subtraction.
Our "greater-than" procedure from Exercise 5 takes more time than I have patience for, so let's make a supercombinator that does it:
curry > { x y } { [expr { ([lazyEval $x] > [lazyEval $y]) ? true : false }] }
# Then here is the 'gcd' procedure, in full.
set gcd [lambda gcd [lambda m [lambda n { > n m { gcd n m } { zero? n m { gcd { - m n } n } } }]]] puts "gcd = $gcd" macro gcd $gcd demonstrate {Y gcd 48 78}