Conference: Week 2

Table Of Contents

Lecture Material

Function vs. Imperative Programming


Lambda Calculus Basics

Consider the following \(\lambda\)-calculus expression \(M\):

M = (λy.y + y)((λx.x + x) 3)
  1. Reduce \(M\) in two different ways:

    1. Always evaluate the right-most reducible \(\lambda\) term.
    2. Always evaluate the left-most reducible \(\lambda\) term.
  2. Which corresponds to the way in which you imagine most programming languages evaluate function calls and the parameters passed to them?

  3. Which reduction is longer? Can you construct another term \(M'\) so that the opposite strategy yields the longer reducton? It need not compute the same value as \(M\). One way to approach this is to think abut how you could change \(M\) to achieve the effect you want.

Lambda Calculus Homework Questions

All good?

[Extra] Church Numerals and Arithmetic

I said in lecture that variables, function definition, and function application are sufficient to capture the essence of every programming language. While we often use them for convenience, not even numbers and math operations are unnecessary. The next two questions illustrates that by showing how to encode arithmetic and recursion using only the 3 core \(\lambda\) calculus features. Any other feature of a programming language can be similarly encoded.

Church numerals are an encoding of Natural numbers in \(\lambda\) calculus. The first few numbers are defined as follows:

0 := λf.λx.x
1 := λf.λx.f x
2 := λf.λx.f (f x)
3 := λf.λx.f (f (f x))
4 := λf.λx.f (f (f (f x)))

We can also encode basic math operations using only function definition, application, and variables. For example:

PLUS := λm.λn.λf.λx.m f (n f x)
MULT := λm.λn.λf.m (n f)

Demonstrate how this works by showing that 1 + 2 == 3:

(PLUS 1) 2 
  = ((λm.λn.λf.λx. (m f)(n f x)) (λf.λx.f x)) (λf.λx.f (f x)) 
  = ...
  = λf.λx.f (f (f x))
  = 3

[Extra] The Y Combinator

We can also write recursive functions in \(\lambda\)-calculus, although doing so requires a little additional work and the Y combinator:

Y := λg.(λx.g (x x)) (λx.g (x x))

(Yes, the start-up incubator Y Combinator is named after this \(\lambda\) term. That company was founded by some of those involved in ViaWeb/Yahoo StoreFront from a couple lectures ago…)

The Y combinator has a key property that enables us to produce recursive computation. Specifically, for some term g:

Y g = (λh.(λx.h (x x)) (λx.h (x x))) g 
    = (λx.g (x x)) (λx.g (x x)) 
    = g ((λx.g (x x)) (λx.g (x x))) 
    = g (Y g)
    = g (g (Y g))
    = g (g (g (Y g)))
    = ...

Now suppose G is

G := λr. λn.(if n = 1 then 1 else n × (r (n−1)))

Show that (Y G) 3 computes \(3!\):

(Y G) 3 = (G (Y G)) 3 
        = ((λr.λn.(if n = 1 then 1 else n × (r (n−1)))) (Y G)) 3
        = ...
        = 3 × (2 × 1)
        = 6