# Lecture 7 — 2015-09-23

## Church encodings: functions all the way down

This lecture is written in literate Haskell; you can download the raw source.

We carried on valiantly with the Church numerals. I reproduce the earlier definitions here, for your convenience.

First, we have the equational rules for the lambda calculus.

(λ x. e) | =_{α} |
(λ y. e[y/x]) |

(λ x. e_{1}) e_{2} |
= | e_{1}[^{e2}/_{x}] |

The Church booleans and cond.

true | = | λ x. &lambda y. x |

false | = | λ x. &lambda y. x |

cond | = | λ p. λ t. λ e. p t e |

The Church numerals and the successor function.

zero | = | λs. λz. z |

one | = | λs. λz. s z |

two | = | λs. λz. s (s z) |

… | ||

succ | = | λn. λs. λz. s (n s z) |

We spent most of class working with the Church numerals.

isZero = λn. n (λx. false) true

plus = λn. λm. n succ m

times = λn. λm. n (m plus) zero

**Church pairs**

We’re not explicitly working with types, but Church pairs do have the following type.

`type ChurchPair a b = (a -> b -> c) -> c`

pair = λa. λb. c a b

A pair is a function that *you* call, and it will tell you what the two values are. We can write functions that get the first and second parts of a pair out:

fst = λp. p (λa b. a) snd = λp. p (λa b. b)

Using pairs, we can define the *predecessor* function, which computes n-1 for all n > 0. For 0, we go ahead and return 0.

We defined the function in class as follows:

pred = λn. λs. λz. snd (n (λp. pair (s (fst p)) (fst p)) (pair z z))

Though we also could have written it:

pred = λn. snd (n (λp. pair (succ (fst p)) (fst p)) (pair zero zero))

**Recursion**

The lambda calculus doesn’t have recursion built in, but we can do it anyway.

Consider the term ω = λx. x x. What does ω do when applied to itself? It reduces right away to itself! This is kind of like running forever—(ω *omega;) will happily churn away, looping on its own forever.

We can use a behavior like this get recursion in the lambda caluclus, by using the *paradoxical Y combinator*.

Y = λf. (λx. f (x x)) (λx. f (x x))

We have, for all expression e:

Y e =_{β} (λx. e (x x)) (λx. e (x x))

If we reduce one more step by β, we get:

e (λx. e (x x)) (λx. e (x x))

Note that the later term is the same as Y e, so:

Y e = e (Y e) = e (e (Y e)) = … and so on infinitely.

Whoa. How do we use this? Here’s a definition for factorial, and a derivation for running it on 3.

ff = (λfact. λn. cond (isZero n) one (times n (fact (pred n))))

factorial = Y ff

**A derivation**

factorial 3

=substituting factorial

(Y ff) 3

=substituting Y

((λf. (λx -> f (x x)) (λx -> f (x x)))) ff) 3

=_{β}

((λx. ff (x x)) (λx. ff (x x))) 3

=_{β}

ff ((λx. ff (x x)) (λx. ff (x x))) 3

NB we’ve already seen that Y ff = ((λx. ff (x x)) (λx. ff (x x))), so

= ff (Y ff) 3

=_{β}

cond (isZero 3) one (times 3 ((Y ff) (pred 3)))

=_{β}

cond (3 (λ_. false) true) one (times 3 ((Y ff) (pred 3)))

=_{β}

cond false one (times 3 ((Y ff) (pred 3)))

=_{β}

(λp t e. p t e) false one (times 3 ((Y ff) (pred 3)))

=_{β}

false one (times 3 ((Y ff) (pred 3)))

=

(λx y. y) one (times 3 ((Y ff) (pred 3)))

=_{β}

(times 3 ((Y ff) (pred 3)))

= (not writing out pred, yeesh)

times 3 ((Y ff) 2)

= from before

times 3 ((ff (Y ff)) 2)

=_{β}

times 3 (cond (isZero 2) 1 (times 2 ((Y ff) (pred 2))))

=_{β} (speeding up a bit now!)

times 3 (times 2 ((Y ff) 1))

=_{β}

times 3 (times 2 (cond (isZero 1) 1 (times 1 ((Y ff) (pred 1)))))

=_{β}

times 3 (times 2 (times 1 ((Y ff) (pred 1))))

= (not writing out pred)

times 3 (times 2 (times 1 ((Y ff) 0)))

=_{β}

times 3 (times 2 (times 1 (cond (isZero 0) 1 (times 0 ((Y ff) (pred 0))))))

=_{β}

times 3 (times 2 (times 1 1))

=_{β}

times 3 (times 2 1)

=_{β}

times 3 2

=_{β}

6

Whew!

**Another way to use Y combinator**

It might be hard to figure out how to use Y. Here’s a step-by-step recipe for how to go from Haskell code to code using the Y combinator.

```
factorial 0 = 1
factorial n = n * factorial (n-1)
```

First step: eliminate pattern matching, since the lambda calculus doesn’t have that. Let’s rewrite this to use an if statement.

`factorial n = if n == 0 then 1 else n * factorial (n-1)`

Second step: write explicit lambdas.

`factorial = \n -> if n == 0 then 1 else n * factorial (n-1)`

Third step: use Church encondings.

`factorial = \n -> cond (isZero n) 1 (times n (factorial (pred n)))`

Fourth step: eliminate explicit recursion using Y. To do this, we come up with a new name—here, `fact`

—and add it as a new parameter to our function. We’ll use `fact`

to do a recursive call, and pass our whole function to Y.

`factorial = Y (\fact -> \n -> cond (isZero n) 1 (times n (fact (pred n))))`

Fifth and final step: translate to lambda calculus syntax! This amounts to changing arrows to dots and giving the slashes little legs to make them lambdas.

factorial = Y (λfact. λn. cond (isZero n) 1 (times n (fact (pred n)))