# COMS W4115 Programming Languages and Translators Lecture 23: April 20, 2015 The Lambda Calculus - II

## Outline

• The influence of the lambda calculus on programming languages
• The Church-Rosser theorems
• The Y combinator
• Implementing factorial using the Y combinator
• Church numerals
• Arithmetic
• Logic
• Other programming language constructs

## 1. The Influence of the Lambda Calculus on Programming Languages

• The lambda calculus is the programming model for functional languages such as Haskell, ML, and OCaml.
• Constructs such as lambda expressions have appeared in many other languages.
• Here are four examples of anonymous functions in lambda form from Python2.7. The syntax of a lambda function is
• lambda argument_list: expression
The functions `map()`, `filter()`, and `reduce()` are built-in functions in Python2.7.

1. Here is a lambda function of two arguments that returns their product:
• ``` >>> (lambda x, y: x*y)(2, 3) 6 ```

2. The function `map(f, seq)` applies the function `f` to all the elements in `seq`. Here is a Python2.7 program that squares every member of a list:
• ``` >>> squares = map(lambda x: x**2, range(5)) >>> print squares [0, 1, 4, 9, 16] ```

3. The function `filter(f, list)` will filter out all the elements of `list` for which the function `f` returns `True`. Here is a Python2.7 program that prints all squares greater than 5 and less than 50:
• ``` >>> squares = map(lambda x: x**2, range(8)) >>> sqs_in_range = filter(lambda x: x > 5 and x < 50, squares) >>> print sqs_in_range [9, 16, 25, 36, 49] ```

4. The function `reduce(f, seq)` continually applies the function `f` to the sequence `seq`. It returns a single value. Here is a Python2.7 program that multiplies the elements in the list `[1,2,3,4,5]`:
• ``` >>> reduce(lambda x, y: x*y, [1,2,3,4,5]) 120 ```

The function `reduce` first multiples 1 and 2 and reduces the list to `[2,3,4,5]`. It then multiplies 2 and 3 and reduces the list to `[6,4,5]`, and so on until only the element 120 is left which is returned as the result.

## 2. The Church-Rosser Theorems

• A remarkable property of lambda calculus is that every expression has a unique normal form if one exists.
• Church-Rosser Theorem I: If `e →* f` and `e →* g` by any two reduction orders, then there always exists a lambda expression `h` such that `f →* h` and `g →* h`.
• A corollary of this theorem is that no lambda expression can be reduced to two distinct normal forms. To see this, suppose `f` and `g` are in normal form. The Church-Rosser theorem says there must be an expression `h` such that `f` and `g` are each reducible to `h`. Since `f` and `g` are in normal form, they cannot have any redexes so `f = g = h`.
• This corollary says that all reduction sequences that terminate will always yield the same result and that result must be a normal form.
• The term confluent is often applied to a rewriting system that has the Church-Rosser property.
• Church-Rosser Theorem II: If `e →* f` and `f` is in normal form, then there exists a normal order reduction sequence from `e` to `f`.

## 3. The Y Combinator

• The `Y` combinator (sometimes called the paradoxical combinator) is a function that takes a function `G` as an argument and returns `G(YG)`. With repeated applications we can get `G(G(YG)), G(G(G(YG))),... `.
• We can implement recursive functions using the `Y` combinator.
• `Y` is defined as follows:
• ```(λf.(λx.f(x x))(λx.f(x x))) ```
• Let us evaluate `YG` where `G` is any expression:
• ```(λf.(λx.f(x x))(λx'.f(x' x'))) G → (λx.G(x x))(λx'.G(x' x')) → G((λx'.G(x' x'))(λx'.G(x' x'))) ↔ G((λf.(λx.f(x x))(λx.f(x x)))G) = G(YG)```
• Thus, `YG →* G(YG)`; that is, `YG` reduces to a call of `G` on `(YG)`.
• We will use `Y` to implement recursive functions.
• `Y` is an example of a fixed-point combinator.

## 4. Implementing Factorial using the Y Combinator

• If we could name lambda abstractions, we could define the factorial function with the following recursive definition:
• `FAC = (λn.IF (= n 0) 1 (* n (FAC (- n 1 ))))`
where `IF` is a conditional function.
• However, functions in lambda calculus cannot be named; they are anonymous.
• But we can express recursion as the fixed-point of a function `G`. To do this, let us simplify the essence of the problem. We begin with a skeletal recursive definition:
• `FAC = λn.(... FAC ...)`
• By performing beta abstraction on `FAC`, we can transform its definition to:
• `FAC = (λf.(λn.(... f ...))) FAC`
`    = G FAC`
where
`G = λf.λn.IF (= n 0) 1 (* n (f (- n 1 )))`
Beta abstraction is just the reverse of beta reduction.
• The equation
• `FAC = G FAC`
says that when the function `G` is applied to `FAC`, the result is `FAC`. That is, `FAC` is a fixed-point of `G`.
• We can use the Y combinator to implement `FAC`:
• `FAC = Y G`
• As an example, let compute `FAC 1`:
• ```FAC 1 = Y G 1       = G (Y G) 1       = λf.λn.IF (= n 0) 1 (* n (f (- n 1 ))))(Y G) 1       → λn.IF (= n 0) 1 (* n ((Y G) (- n 1 ))))1       → IF (= n 0) 1 (* n ((Y G) (- 1 1 )))       → * 1 (Y G 0)       = * 1 (G(Y G) 0)       = * 1((λf.λn.IF (= n 0) 1 (* n (f (- n 1 ))))(Y G 0)       → * 1((λn.IF (= n 0) 1 (* n ((Y G) (- n 1 ))))0       → * 1(IF (= 0 0) 1 (* 0 ((Y G) (- 0 1 )))       → * 1 1       → 1```

## 5. Church Numerals

• Church numberals are a way of representing the integers in lambda calculus.
• Church numerals are defined as functions taking two parameters:
• `0` is defined as `λf.λx. x`
`1` is defined as `λf.λx. f x`
`2` is defined as `λf.λx. f (f x)`.
`3` is defined as `λf.λx. f (f (f x))`.
`n` is defined as `λf.λx. fn x`
• `n` has the property that for any lambda expressions `g` and `y`, `ngy →* gny`. That is to say, `ngy` causes `g` to be applied to `y` n times.

## 6. Arithmetic

• In lambda calculus, arithmetic functions can be represented by corresponding operations on Church numerals.
• We can define a successor function `succ` of three arguments that adds one to its first argument:
• `λn.λf.λx. f (n f x)`
• Example: Let us evaluate `succ 0`:
• ```(λn.λf.λx. f (n f x)) 0    → λf.λx. f (0 f x)    = λf.λx. f ((λf.λx. x) f x)    → λf.λx. f (λx. x) x)    → λf.λx. f x    = 1```
• We can define a function `add` using the identity ```f(m+n) = fm º fn``` as follows:
• `λm.λn.λf.λx. m f (n f x)`
• Example: Let us evaluate `add 1 2`:
• ```λm.λn.λf.λx. m f (n f x) 1 2    →  λn.λf.λx. 1 f (n f x) 2    →* λf.λx. f (f (f x))    =  3```

## 7. Logic

• The boolean value true can be represented by a function of two arguments that always selects its first argument: `λx.λy.x`
• The boolean value false can be represented by a function of two arguments that always selects its second argument: `λx.λy.y`
• An if-then-else statement can be represented by a function of three arguments `λc.λi.λe. c i e` that uses its condition `c` to select either the if-part `i` or the else-part `e`.
• Example: Let us evaluate if true then 1 else 2:
• ```(λc.λi.λe. c i e) true 1 2    → (λi.λe. true i e) 1 2    → (λe. true 1 e) 2    → true 1 2    = (λx.λy.x) 1 2    → (λy.1) 2    → 1 ```
• The boolean operators and, or, and not can be implemented as follows:
• ``` and = λp.λq. p q p or  = λp.λq. p p q not = λp.λa.λb. p b a ```
• Example: Let us evaluate `not true`:
• ```(λp.λa.λb. p b a) true    → λa.λb. true b a    = λa.λb. (λx.λy.x) b a    → λa.λb. (λy.b) a    → λa.λb. b    = false ``` (under renaming)

## 8. Other Programming Language Constructs

• We can readily implement other programming language constructs in lambda calculus. As an example, here are lambda calculus expressions for various list operations such as cons (constructing a list), head (selecting the first item from a list), and tail (selecting the remainder of a list after the first item):
• ``` cons = λh.λt.λf. f h t head = λl.l (λh.λt. h) tail = λl.l (λh.λt. t) ```

## 9. Practice Problems

1. Evaluate ```((λx.((λw.λz. + w z)1)) ((λx. xx)(λx. xx))) ((λy. * y 1) (- 3 2))``` using normal order evaluation and applicative order evaluation.
2. Give an example of a code optimization transformation that has the Church-Rosser property.
3. Evaluate `FAC 2`.
4. Evaluate `succ two`.
5. Evaluate `add two three`.
6. Let `mul` be the function
• `λm.λn.λf.λx. m (n f x)`
Evaluate `mul two three`.
7. Write a lambda expression for the boolean predicate `isZero` and evaluate `isZero one`.

## 10. References

aho@cs.columbia.edu