Functions as data
Matthew Hennessy
April 2, 2015
Lambda Matthew Hennessy
Notation for functions
Anonymous functions
I λx .x + 3 - from numerals to numerals
I λf .f (2) - from functions to numerals
I λx .if x = 0 then λy .y else λy .x - from numerals to
functions
I λf .λx .if x = 0 then 1 else (let y = f (x − 1) in x × y ) -
from functions to functions
I λf .λg . λx .f (g (x)) - from pairs of functions to functions
Lambda Matthew Hennessy
The Lambda-calculus
M ∈ Lambda ::= v
| M1 + M2
| M1 and M2 | M1 or M2 | M1 = M2 | M1 < M2
| if M1 then M2 else M2
| let x = M1 in M3
| M1 M2
v ∈ Val ::= x ∈ Vars | n ∈ Nums | tt | ff | λx .M
I M1 M2 : apply function M1 to M2 or App(M1 , M2 )
I λx .M: anonymous function which when applied to data N
executes M{|N/x |}
Lambda Matthew Hennessy
Free variables
I fv(x) = {x} fv(n) = fv(tt) = fv(ff) = {}
I fv(M1 op M2 ) = fv(M1 ) ∪ fv(M2 )
I fv(M1 M2 ) = fv(M1 ) ∪ fv(M2 )
I fv(let y = M1 in M2 ) = fv(M1 ) ∪ (fv(M2 ) − {y })
I fv(λx .M) = fv(M) − {x}
Closed terms:
M is closed if fv(M) = {}
Closed terms correspond to programs
Lambda Matthew Hennessy
Small-step semantics
Judgements:
M →N
where M, N are programs
Intuition:
M performs
I one function application
I or one built-in operation
and N remains to be evaluated
Lambda Matthew Hennessy
Semantic rules
Standard rules:
(s-left)
M1 → M10
(M1 + M2 ) → (M10 + M2 )
(s-right)
M2 → M20
(n1 + M2 ) → (n1 + M20 )
(s-add)
n3 = add(n1 , n1 )
(n1 + n2 ) → n3
Similar rules for or and, if then else . . .
Lambda Matthew Hennessy
Semantic rules
To evaluate let x = M in E
I Keep evaluating M to obtain a value v.
I Then substitute v in for x in E and continue evaluating
(s-let)
M → M0
(1)
let x = M in E → let x = M 0 in E
(s-let.subs)
(2)
let x = v in E → E {|v/x |}
Lambda Matthew Hennessy
Function application
To evaluate M1 M2 :
I evaluate M1 to a function λx .M
Call-by-value\eager: Call-by-name\lazy:
I evaluate M2 to a value v I evaluate M{|M2/x |}
I evaluate M{|v/x |}
v ∈ Val ::= n | tt | ff | λx .N
Lambda Matthew Hennessy
Function application
(l-app)
M1 →e M10
M1 M2 →e M10 M2
Call-by-value\eager:
(l-cbv.a) (l-cbv)
M2 →e M20
(λx .M)M2 →e (λx .M)M20 (λx .M)v →e M{|v/x |}
Values:
v ∈ Val ::= n | tt | ff | λx .N
Lambda Matthew Hennessy
Function application
(l-app)
M1 →l M10
M1 M2 →l M10 M2
Call-by-name\lazy:
(l-cbn)
(λx .M)M2 →l M{|M2/x |}
Note:
M2 is a closed term
Lambda Matthew Hennessy
Substitution of closed terms
N closed:
I x{|N/x |} = N
I y {|N/x |} = y y 6= x
I (λx .M){|N/x |} = λx .M
I (λy .M){|N/x |} = λy .(M{|N/x |})
I (M1 M2 ){|N/x |} = (M1 {|N/x |})(M2 {|N/x |})
I (M1 op M2 ){|N/x |} = (M1 {|N/x |}) op (M2 {|N/x |})
I .........
N open:
Not defined
Lambda Matthew Hennessy
Self-application eager and lazy semantics
∆ , λx .x x
∆∆ → ∆∆ → ∆∆ → . . . . . . ∆∆ → . . . . . .
Non-termination is built-in to Lambda
Lambda Matthew Hennessy
Eager v. lazy
They give different results:
I (λx .0)(∆∆) →l 0
I (λx .0)(∆∆) →e . . . →e . . . →e . . .
I (λx .λy .x) (Id 0) →∗e λy .0
I (λx .λy .x) (Id 0) →∗l λy .(Id 0)
See Pierce pp. 56 for different evaluation strategies
Lazy very inefficient a priori
(λx .x + x + x) M →l M + M + M
Lambda Matthew Hennessy
Fixpoints via Turings combinator
A ,λx .λy .y (xxy )
Θ ,A A
For any program P: lazy
Θ P →l (λy .y (AAy ))P
→l P(ΘP)
Choose P of form λf .λx .B:
Θ (λf .λx .B) →∗l (λf .λx .B) (Θ λf .λx .B)
→l λx .B{|Θ (λf .λx .B)
/f |}
With Θ recursive functions can be defined.
Lambda Matthew Hennessy
Fixpoints
For any program P: Θ P →l (λy .y (AAy ))P
→l P(ΘP)
Θ (λf .λx .B) →∗l (λf .λx .B) (Θ λf .λx .B)
→l λx .B{|Θ (λf .λx .B)
/f |}
Recursive definitions:
recf .B abbreviation for Θ (λf .λx .B)
recf .B →∗l λx .B{|recf .B/f |}
Lambda Matthew Hennessy
Example: the factorial function
.
λf .λx .if x = 0 then 1 else x × f (x − 1)
= λf .λx .F
recf .F = recursive definition of factorial
.
recf .F →∗l λx .if x = 0 then 1 else x × (recf .F ) (x − 1)
(recf .F ) 3
→∗l (λx .if x = 0 then 1 else x × (recf .F ) (x − 1)) 3
→∗l 3 × (recf .F ) 2
→∗l 3 × (λx .if x = 0 then 1 else x × (recf .F ) (x − 1)) 2
→∗l 3 × 2 × (recf .F ) 1
→∗l 3 × 2 × 1 × (recf .F ) 0
→∗l 3 × 2 × 1 × 1
→∗l 6
Lambda Matthew Hennessy
Fixpoints in the eager operational semantics
A ,λx .λy .y (xxy ) Θ,AA
For any program P: eager
Θ P →e (λy .y (AAy ))P A is a value
→e P(ΘP) if P is a value
Choose P of form λf .λx .B: a value
Θ (λf .λx .B) →∗e (λf .λx .B) (Θ λf .λx .B)
→l λx .B{|Θ (λf .λx .B)
/f |}
6→e λx .B{|Θ (λf .λx .B)
/f |}
(Θ λf .λx .B) is not a value
Lambda Matthew Hennessy
Eager evaluation of fixpoints
Θ (λf .λx .B) →∗e (λf .λx .B) (Θ λf .λx .B)
→∗e (λf .λx .B)(λf .λx .B) (Θ λf .λx .B)
→∗e (λf .λx .B)(λf .λx .B)(λf .λx .B) (Θ λf .λx .B)
→∗e . . . . . . forever
Solution we need to stop the indefinite unfolding of (Θ (λf .λx .B))
Lambda Matthew Hennessy
η-expansion
What is the difference between
Q λz .Q z? z not free in Q
Not much
(Θ (λf .λx .B) vs λz .(Θ (λf .λx .B)) z
One is a value, the other is not
Lambda Matthew Hennessy
Eager fixpoints
Late combinator:
A ,λx .λy .y (xxy ) Θ,AA
Early combinator:
Av ,λx .λy .y λz .(xxy )z Θv , Av Av
For any program P:
Θv P →e (λy .y λz .(Av Av y )z) P
→e P λz .(Θv P)z
Lazy: Θ P →l P (Θ P)
Lambda Matthew Hennessy
Eager recursive functions
recv f .B abbreviation for Θv (λf .λx .B)
recv f .B →∗e λf .λx .B) λz .recv f .B z
→∗e λx .B{|λz .(recv f .B) z/f |}
recv f .B v →∗e B{|λz .(recv f .B) z/f |} {|v/x |}
Lambda Matthew Hennessy
Example: the factorial function
.
λf .λx .if x = 0 then 1 else x × f (x − 1)
= λf .λx .F
recv f .F = recursive definition of factorial
recv f .F →∗e λx .if x = 0 then 1 else
.
x × (λz .recv f .F z) (x − 1)
(recv f .F ) 3
→∗e (λx .if x = 0 then 1 else x × (λz .recv f .F z) (x − 1)) 3
→∗e 3 × (λz .recv f .F z) 2
→∗e 3 × (recv f .F ) 2
→∗ . . .
Lambda Matthew Hennessy
The Lambda-calculus
M ∈ Lambda ::= v | M1 + M2
| M1 and M2 | M1 or M2 | M1 = M2 | M1 < M2
| if M1 then M2 else M2
| let x = M1 in M3
| M1 M2
v ∈ Val ::= x ∈ Vars | n ∈ Nums | tt | ff | λx .M
Equivalent:
M ∈ Lambda ::= x ∈ Vars | n ∈ Nums | λx .M
| M1 + 1 | Eq0 | M1 M2
Lambda Matthew Hennessy
The Lambda-calculus
M ∈ Lambda ::= x ∈ Vars | n ∈ Nums | λx .M
| M1 + 1 | Eq0 | M1 M2
Equivalent:
M ∈ Lambda ::= x ∈ Vars | λx .M | M1 M2
Arithmetic implemented using Church numbers
Lambda Matthew Hennessy
Church numbers
0 = λf .λx .x 1 = λf .λx .f x 2 = λf .λx .f (f x) . . .
n = λf .λx .f n x
Succ = λn .λf .λx .f (n f x)
Succ 1 = λf .λx .f (1 f x)
= 2 = λf .λx .f (f x) up to some theory
Eq0 : λn .n (λx .False) True
Eq0 0 →∗ True Eq0 1 →∗ False Eq0 2 →∗ False . . .
Lambda Matthew Hennessy
The Lambda-calculus
M ∈ Lambda ::= x ∈ Vars | λx .M | M1 M2
As a programming language:
I eager evaluation strategy
I lazy evaluation strategy
As a mathematical theory:
I Allow arbitrary reductions of redexes
Lambda Matthew Hennessy