Lambda
Lambda
Stephen A. Edwards
Columbia University
Fall 2021
Lambda Expressions
Function application written in prefix form. “Add four and five” is
(+ 4 5)
The only other thing in the lambda calculus is lambda abstraction: a notation
for defining unnamed functions.
(λx . + x 1)
( λ x . + x 1)
↑ ↑ ↑ ↑ ↑ ↑
That function of x that adds x to 1
or not at all
(λx . 3) 5 → 3
Beta-Reduction
Fussy, but mechanical. Extra parentheses may help.
õ ¶ !
³ ¢´
(λx . λy . + x y) 3 4 λx . λy . (+ x) y
¡
= 3 4
à !
λy .
¡ ¢
→ (+ 3) y 4
¡ ¢
→ (+ 3) 4
→ 7
(λx . + x y) 4
so
(λx . (λx . + (− x 1)) x 3) 9 → (λ x . + (− x 1)) 9 3
→ + (− 9 1) 3
→ +83
→ 11
Another Example
³ ¢´ ³ ¢´
λx . λy . + x (λx . − x 3) y 5 6 → λy . + 5 (λx . − x 3) y 6
¡ ¡
→ + 5 (λx . − x 3) 6
¡ ¢
→ + 5 (− 6 3)
→ +53
→ 8
Alpha-Conversion
One way to confuse yourself less is to do α-conversion: renaming a λ
argument and its bound variables.
Formal parameters are only names: they are correct if they are consistent.
(λx . (λx . + (− x 1)) x 3) 9 ↔ (λx . (λy . + (− y 1)) x 3) 9
→ ((λy . + (− y 1)) 9 3)
→ (+ (− 9 1) 3)
→ (+ 8 3)
→ 11
(λx . λy . y) ( · · · )
However,
(λz . z z) (λz . z z) → (λz . z z) (λz . z z)
(λx . λy . y) ( · · · ) → (λy . y)
Normal Form
Not all expressions have normal forms, but is there a reliable way to find the
normal form if it exists?
à !
³ ¢´ ¡
λx . (λw . λz . + w z) 1 (λx . x x) (λx . x x) (λy . + y 1) (+ 2 3)
¡ ¢ ¡ ¢
leftmost outermost
λx λy
leftmost innermost λx λx 3
λw 1 1 + 2
x x x x + y
λz
z
+ w
Boolean Logic in the Lambda Calculus
“Church Booleans”
true = λx . λy . x
false = λx . λy . y
E.g.,
ifelse true 42 58 = true 42 58
→ (λx . λy . x) 42 58
→ (λy . 42) 58
→ 42
Boolean Logic in the Lambda Calculus
Logic operators can be expressed with if-then-else:
and = λp . λq . p q p
or = λp . λq . p p q
not = λp . λa . λb . p b a
λn . λf . λx . f (n f x) 2
¡ ¢
succ 2 =
→ λf . λx . f (2 f x)
µ ¶
= λf . λx . f λf . λx . f (f x) f x
¡ ¢
→ λf . λx . f f (f x)
¡ ¢
= 3
Adding Church Numerals
Finally, we can add:
plus = λm.λn.λf .λx . m f ( n f x)
λm.λn.λf .λx . m f ( n f x) 3 2
¡ ¢
plus 3 2 =
→ λf .λx . 3 f ( 2 f x)
→ λf .λx . f (f (f (2 f x)))
→ λf .λx . f (f (f (f ( f x))))
= 5
mult = λm.λn.λf .m (n f)
λm.λn.λf .m (n f) 2 3
¡ ¢
mult 2 3 =
→ λf . 2 (3 f)
→ λf . 2 (λx . f(f(f x)))
↔α λf . 2 (λy . f(f(f y)))
→ λf . λx . (λy . f(f(f y))) ((λy . f(f(f y))) x)
→ λf . λx . (λy . f(f(f y))) (f(f(f x)))
→ λf . λx . f(f(f (f(f(f x))) ))
= 6
Recursion
Where is recursion in the lambda calculus?
à !
³ ¢´
λn . if (= n 0) 1 ∗ n fac (− n 1)
¡
fac =
This does not work: functions are unnamed in the lambda calculus. But it is
possible to express recursion as a function.
fac = (λn . . . . fac . . .)
←β (λf . (λn . . . . f . . .)) fac
= H fac
That is, the factorial function, fac, is a fixed point of the (non-recursive)
function H:
H = λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
= ∗ 1 ((λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 0)
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
= ∗ 1 ((λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 0)
→ ∗ 1 ((λn . if (= n 0) 1 (∗ n (Y H (− n 1)))) 0)
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
= ∗ 1 ((λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 0)
→ ∗ 1 ((λn . if (= n 0) 1 (∗ n (Y H (− n 1)))) 0)
→ ∗ 1 (if (= 0 0) 1 (∗ 0 (Y H (− 0 1))))
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
= ∗ 1 ((λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 0)
→ ∗ 1 ((λn . if (= n 0) 1 (∗ n (Y H (− n 1)))) 0)
→ ∗ 1 (if (= 0 0) 1 (∗ 0 (Y H (− 0 1))))
→ ∗11
Recursion
Let’s invent a Y that computes fac from H, i.e., fac = Y H:
fac = H fac
Y H = H (Y H)
fac 1 = Y H 1
= H (Y H) 1
= (λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 1
→ (λn . if (= n 0) 1 (∗ n ((Y H) (− n 1)))) 1
→ if (= 1 0) 1 (∗ 1 ((Y H) (− 1 1)))
→ ∗ 1 (Y H 0)
= ∗ 1 (H (Y H) 0)
= ∗ 1 ((λf . λn . if (= n 0) 1 (∗ n (f (− n 1)))) (Y H) 0)
→ ∗ 1 ((λn . if (= n 0) 1 (∗ n (Y H (− n 1)))) 0)
→ ∗ 1 (if (= 0 0) 1 (∗ 0 (Y H (− 0 1))))
→ ∗11
→ 1
The Y Combinator
Here’s the eye-popping part: Y can be a simple lambda expression.
Y =
λf . λx . f (x x) λx . f (x x)
¡ ¢¡ ¢
=
³ ¢´
λf . λx . f (x x) λx . f (x x) H
¡ ¢¡
YH =
→ λx . H (x x) λx . H (x x)
¡ ¢¡ ¢
³¡ ¢´
→ H λx . H (x x) λx . H (x x)
¢¡
µ³ ¶
¢´
↔ H λf . λx . f (x x) λx . f (x x) H
¡ ¢¡
= H (Y H)
“Y: The function that takes a function f and returns f(f(f(f(· · · ))))”
Alonzo Church
1903–1995
Professor at Princeton (1929–1967)
and UCLA (1967–1990)
Invented the Lambda Calculus
Had a few successful graduate students, including
Ï Stephen Kleene (Regular expressions)
Ï Michael O. Rabin† (Nondeterministic automata)
Ï Dana Scott† (Formal programming language semantics)
Ï Alan Turing (Turing machines)
†
Turing award winners
Turing Machines vs. Lambda Calculus
In 1936,
Ï Alan Turing invented the Turing machine
Ï Alonzo Church invented the lambda calculus