Lecture 6 (2015-09-21) Stack machines; the lambda calculus **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. e1) e2 = e1[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| |(e1 e2)[e/x] |=| e1[e/x] e2[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 e1 e2 = e1 and: cond false e1 e2 = e2 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)