# Lecture 6 — 2015-09-21

## Stack machines; the lambda calculus

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

**Stack machines**

Command | Input stack | Output stack | |
---|---|---|---|

IPush n | s | –> | n:s |

IPlus | n1:n2:s | –> | n1 + n2:s |

ITimes | n1:n2:s | –> | n1 * n2:s |

INeg | n:s | –> | (0-n):s |

**The lambda calculus**

The lambda calculus is a notation for *anonymous* functions. We typically write math functions with names, like: f(x) = x + 1. In the lambda calculus, we write functions anonymously. For example, f is equivalent to λx. x + 1.

We introduced an *equational* semantics with two axioms.

The first, *alpha equivalence*, says that we can rename variables so long as we do it consistently:

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

The second, *beta equivalence*, says how to apply functions:

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

A variable is *free* when it’s not under λ that binds it. In λx. x y, the variable y is free but x is *bound*.

We defined substitution as follows:

x[e/x] | = | e |

y[e/x] | = | y |

(e_{1} e_{2})[e/x] |
= | e_{1}[e/x] e_{2}[e/x] |

(λx. e’)[e/x] | = | λx. e’ |

(λy. e’)[e/x] | = | λy. e’[e/x] |

Note that the definition above only *really* makes sense when e—the term being substituted for x—doesn’t have free variables. When e has free variables, we need to worry about *capture*, where a free variable in e becomes bound. The standard way of defining capture-avoiding substitution is to imagine that we have some infinite source of *fresh* variables, which don’t appear in any given term we’re considering. We then change the last line to read:

(λy. e’)[e/x] = λz. e’[z/y][e/x] where z is fresh

The freshness of z makes sure that neither e’ nor e mention z at all.

**Church encodings**

We also defined a bunch of *Church encodings*, named after Alonzo Church, the progenitor and master encoder of the lambda calculus.

We first defined the Church booleans:

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

Then, to check our work, we defined a conditional:

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

We can then see that:

cond true e_{1} e_{2} = e_{1}

and:

cond false e_{1} e_{2} = e_{2}

That is… it really works! The idea here is to *operationalize* every thing. The booleans are typicaly defined as **2** = { ⊥, ⊤ }, but we instead say that the *Church booleans* are the functions that make a choice between two things.

We can define numbers, too. A *Church numeral* is a function that takes two arguments and applies the first one some number of times.

So 0 is the function that never applies its first argument:

zero = λs. λz. z

And 1 applies it once:

one = λs. λz. s z

And two applies it twice:

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

We can write the *successor function*, which takes a number and then yields its successor.

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

**Types**

Naive Church encodings don’t always work in Haskell due to typing, but we can *think* of each of these Church encodings as having a type.

```
type ChurchBoolean = a -> a -> a
type ChurchNumeral = (a -> a) -> a -> a
```

**Shorthand notation**

When a function takes a bunch of arguments—like succ above—we sometimes write a single lambda, like so:

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