0% found this document useful (0 votes)
2 views38 pages

Lambda

The document provides an overview of Lambda Calculus, including concepts such as lambda expressions, function application, beta-reduction, and recursion. It explains the syntax, evaluation processes, and introduces Church numerals for arithmetic operations. Additionally, it discusses Boolean logic and the representation of functions in the Lambda Calculus framework.

Uploaded by

gogimo1970
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views38 pages

Lambda

The document provides an overview of Lambda Calculus, including concepts such as lambda expressions, function application, beta-reduction, and recursion. It explains the syntax, evaluation processes, and introduces Church numerals for arithmetic operations. Additionally, it discusses Boolean logic and the representation of functions in the Lambda Calculus framework.

Uploaded by

gogimo1970
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

The Lambda Calculus

Stephen A. Edwards

Columbia University

Fall 2021
Lambda Expressions
Function application written in prefix form. “Add four and five” is
(+ 4 5)

Evaluation: select a redex and evaluate it:


(+ (∗ 5 6) (∗ 8 3)) → (+ 30 (∗ 8 3))
→ (+ 30 24)
→ 54

Often more than one way to proceed:


(+ (∗ 5 6) (∗ 8 3)) → (+ (∗ 5 6) 24)
→ (+ 30 24)
→ 54

Simon Peyton Jones, The Implementation of Functional Programming Languages,


Prentice-Hall, 1987.
Function Application and Currying

Function application is written as juxtaposition:


fx

Every function has exactly one argument. Multiple-argument functions are


represented by currying, named after Haskell Brooks Curry (1900–1982). So,
(+ x)

is the function that adds x to its argument.


Function application associates left-to-right:
(+ 3 4) = ((+ 3) 4)
→ 7
Lambda Abstraction

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

In Haskell, this is written


(\x -> (+) x 1)
The Syntax of the Lambda Calculus

expr ::= expr expr


| λ variable . expr
| constant
| variable
| (expr)

Constants are numbers and built-in functions; variables are identifiers.


Function application binds more tightly than λ:
λ x . f g x = λ x . (f g) x
¡ ¢
Beta-Reduction

Evaluation of a lambda abstraction—beta-reduction—is just substitution:


(λx . + x 1) 4 → (+ 4 1)
→ 5

The argument may appear more than once


(λx . + x x) 4 → (+ 4 4)
→ 8

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

Functions may be arguments


(λf . f 3) (λx . + x 1) → (λx . + x 1) 3
→ (+ 3 1)
→ 4
Free and Bound Variables

(λx . + x y) 4

Here, x is like a function argument but y is like a global variable.


Technically, x occurs bound and y occurs free in
(λx . + x y)

However, both x and y occur free in


(+ x y)
Beta-Reduction More Formally
(λx . E) F →β E0

where E0 is obtained from E by replacing every instance of x that appears free


in E with F.
The definition of free and bound mean variables have scopes. Only the
rightmost x appears free in
(λx . + (− x 1)) x 3

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

You’ve probably done this before in C or Java:


int add(int x, int y) int add(int a, int b)
{ {

return x + y; return a + b;
} }
Beta-Abstraction and Eta-Conversion
Running β-reduction in reverse, leaving the “meaning” of a lambda
expression unchanged, is called beta abstraction:
+ 4 1 ← (λx . + x 1) 4

Eta-conversion is another type of conversion that leaves “meaning”


unchanged:
(λx . + 1 x) ↔η (+ 1)

Formally, if F is a function in which x does not occur free,


(λx . F x) ↔η F

int f(int y) { ... }


int g(int x) { return f(x); }

g(w); ← can be replaced with f(w)


Reduction Order
The order in which you reduce things can matter.
(λx . λy . y) (λz . z z) (λz . z z)
¡ ¢

Two things can be reduced:


(λz . z z) (λz . z z)

(λx . λy . y) ( · · · )

However,
(λz . z z) (λz . z z) → (λz . z z) (λz . z z)

(λx . λy . y) ( · · · ) → (λy . y)
Normal Form

A lambda expression that cannot be β-reduced is in normal form. Thus,


λy . y

is the normal form of


(λx . λy . y) (λz . z z) (λz . z z)
¡ ¢

Not everything has a normal form. E.g.,


(λz . z z) (λz . z z)

can only be reduced to itself, so it never produces an non-reducible


expression.
Normal Form

Can a lambda expression have more than one normal form?

Church-Rosser Theorem I: If E1 ↔ E2 , then


there exists an expression E such that E1 → E and E2 → E.

Corollary. No expression may have two distinct normal forms.

Proof. Assume E1 and E2 are distinct normal forms for E: E ↔ E1 and E ↔ E2 . So


E1 ↔ E2 and by the Church-Rosser Theorem I, there must exist an F such that
E1 → F and E2 → F. However, since E1 and E2 are in normal form, E1 = F = E2 , a
contradiction.
Normal-Order Reduction

Not all expressions have normal forms, but is there a reliable way to find the
normal form if it exists?

Church-Rosser Theorem II: If E1 → E2 and E2 is in normal form,


then there exists a normal order reduction sequence from E1 to E2 .

Normal order reduction: reduce the leftmost outermost redex.


Normal-Order Reduction

à !
³ ¢´ ¡
λ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

Each is a function of two arguments: true is “select first;” false is “select


second.” If-then-else uses its predicate to select then or else:
ifelse = λp . λa . λb . p a b

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

and true false = (λp . λq . p q p) true false


→ true false true
→ (λx . λy . x) false true
→ false

not true = (λp . λa . λb . p b a) true


→β λa . λb . true b a
→β λa . λb . b
→α λx . λy . y
= false
Arithmetic: The Church Numerals
0 = λf . λx . x
1 = λf . λx . fx
2 = λf . λx . f (f x) ¢
λf λx
¡
3 = . . f f (f x)

I.e., for n = 0, 1, 2, . . ., nfx = f (n) (x). The successor function:


succ = λn . λf . λx . f (n f x)

λ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

Not surprising since f (m) ◦ f (n) = f (m+n)


The minus function is trickier since there aren’t negative numbers:
minus = λm.λn. (n pred) m
= λm.λn. (n (λn.λf .λx . n (λg.λh. h (g f))(λu. x)(λu. u))) m
Multiplying Church Numerals

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

In 1937, Turing proved that the two models were


equivalent, i.e., that they define the same class of
computable functions.

Modern processors are just overblown Turing machines.


Functional languages are just the lambda calculus with a more palatable
syntax.

You might also like