Lambda Calculus as a programming language

Booleans

We can encode boolean values TRUE and FALSE in lambda calculus as functions that take 2 values, x and y, and return the first (for TRUE) or second (for FALSE) value.

$ TRUE = \lambda x.\lambda y.y$
$ FALSE = \lambda x.\lambda y.x$

As we defined it, TRUE is sometimes called the K-Combinator (or Kestrel), and FALSE the KI-Combinator (or Kite).

Click to display ⇲

Click to hide ⇱

Some common operation on booleans (that were discussed during the lecture) are:

$ AND = \lambda x.\lambda y.((x \ y) \ x) $
$ OR = \lambda x.\lambda y.((x \ x) \ y) $
$ NOT = \lambda x.((x \ FALSE) \ TRUE) $

NOT can also be written as:

$ NOT = \lambda x.\lambda a.\lambda b.((x \ b) \ a) $

You can convince yourself that this works by evaluating $ NOT \ TRUE $ and $ NOT \ FALSE $. This way of writting NOT is also called the C-Combinator (or Cardinal).


1. Define the $ XOR $ operation over booleans.

Pairs

We can also encode data structures . We will only look at one of the simpler ones, the pair.
A pair encapsulates two variables together, that we can later access using $ FIRST $ and $ SECOND $ .

$ PAIR = \lambda x.\lambda y.\lambda f.f \ x \ y $
$ FIRST = \lambda p.p \ TRUE $
$ SECOND = \lambda p.p \ FALSE $

Natural Numbers

Church numerals represent natural numbers as higher-order functions. Under this representation, the number n is a function that maps f to its n-fold composition.

$ N0 = \lambda f.\lambda x. x $
$ N1 = \lambda f.\lambda x. (f \ x) $
$ N2 = \lambda f.\lambda x. (f \ (f \ x)) $

Does N0 look familiar? It's the same as FALSE if you rename the variables (using $\alpha$-reduction).

You can also define operation on church numerals, some (that were discussed during the lecture) are:

$ SUCC = \lambda n.\lambda f.\lambda x.(f \ ((n \ f) \ x)) $
$ ISZERO = \lambda n.((n \lambda x.FALSE) \ TRUE) $
$ ADD = \lambda n.\lambda m.\lambda f.\lambda x.((n \ f) ((m \ f) \ x)) $

2. Define multiplication under church numerals: $ MULT = \lambda n.\lambda m. \ \ldots $ (Hint: you can do it without the Y-Combinator)

3. Define exponentiation under church numerals: $ EXP = \lambda n.\lambda m. \ \ldots $

4. (*) Define the predecessor operator, that takes a number and returns the number prior to it.

What's the predecessor of 0? Evaluate $ PRED \ N0 $.

Solution:

Click to display ⇲

Click to hide ⇱

If use pairs, we can define the shift-and-increment operator:
$ \phi' = \lambda x.PAIR \ x \ (SUCC \ x) $

This takes a number $ n $, and returns a pair made up of the number and it's succesor ( $ n $ , $ SUCC(n) $ ).

To make this function be able to be iterate multiple times, we make the input another pair, where the second value is the 'real' input:
$ \phi = \lambda p.PAIR \ (SECOND \ p) \ (SUCC \ (SECOND \ p)) $

Now we can just iterate this n times starting with $ N0 $, and we get a pair ($ n - 1 $, $ n $), where the first value is our predecesor:
$ PRED = \lambda.n.FIRST \ (n \ \phi \ (PAIR \ N0 \ N0)) $

An alternative solution, that uses a value container is the following (unfortunately, we will not explain this in further detail here):
$ PRED = \lambda n.\lambda f.\lambda x.(((n \ (\lambda g.\lambda h.h \ (g \ f))) \ (\lambda u.x)) \ (\lambda v.v)) $


5. Define substraction under church numerals: $ SUB = \lambda n.\lambda m. \ \ldots $ (Hint: use $ PRED $).

What happens if you try to substract a bigger number from a smaller one? Evaluate $ SUB \ N1 \ N2 $.

6. Define $ LEQ $ (less or equal). $ LEQ \ n \ m $ should return TRUE if $ n \leq m $ and FALSE if $ n > m $.

7. Define $ EQ $ (equality). $ EQ \ n \ m $ should return TRUE if $ n = m $ and FALSE otherwise.

In lambda calculus, recursion is achieved using the fixed-point combinator (or Y combinator, “Why” bird or Sage bird).
A fixed-point combinator is a higher-order function that returns some fixed point of it's argument function (x is a fixed pointed for a function f if $ f(x) = x $). That means: $ f \ (fix \ f) = fix \ f $
And by repeated application: $ fix \ f = f \ (f \ (\ldots f \ (fix \ f)\ldots)) $
The Y-combinator in lambda calculus looks like this:

$ FIX = \lambda f.(\lambda x.f \ (x \ x)) (\lambda x.f \ (x \ x)) $

8. Using the Y-Combinator, define a function that computes the factorial of a number n.

9. Using the Y-Combinator, define a function $ FIB $ that computes the n-th fibonacci number.