the lambda calculus david walker cs 441. the (untyped) lambda calculus a language of functions e ::=...
TRANSCRIPT
the lambda calculus
David Walker
CS 441
the (untyped) lambda calculus• a language of functions
e ::= x | \x.e | e1 e2 v ::= \x.e• there are several different ways to evaluate lambda calculus
expressions• so far, we’ve studied left-to-right, call-by-value:
• amazingly, despite it’s minimalism, the lambda calculus is Turing complete and may serve as a foundation for all computation
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1) (app2)
extending the lambda calculus
• lambda calculus with booleans:
e ::= x | true | false | test | \x.e | e1 e2
v ::= true | false | test | \x.e
test e1 e2 e3 --> test e1’ e2 e3(test1)e1 --> e1’
test v1 e2 e3 --> test v1 e2’ e3(test2)e2 --> e2’
test v1 v2 e3 --> test v1 v2 e3’(test3)e3 --> e3’
test true v2 v3 --> v2(test-true)
test false v2 v3 --> v3(test-false)
+ all the other lambda calculus rules
booleans: the translation
• from +boolean into pure :
translate(true) = \t.\f. t
translate(false) = \t.\f. f
translate(test) = \x.\y.\z. x y z
translate(x) = x
translate(\x.e) = \x.(translate(e))
translate(e1 e2) = translate(e1) translate(e2)
values in the source languagealways get translated into valuesin the target language
source language
target language
boolean translation
example:
translate(test true s1 s2) = (\x.\y.\z.x y z) (\x.\y.x) v1 v2
(where v1 = translate s1
and v2 = translate s2)
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
boolean translation
example:
translate(test true s1 s2) = (\x.\y.\z.x y z) (\x.\y.x) v1 v2
(where v1 = translate s1
and v2 = translate s2)
in the source language we have:
test true s1 s2 --> s1
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
boolean translation
example:
translate(test true s1 s2) = (\x.\y.\z.x y z) (\x.\y.x) v1 v2
(where v1 = translate s1
and v2 = translate s2)
in the source language we have:
test true s1 s2 --> s1
so in the target we want:
(\x.\y.\z.x y z) (\x.\y.x) v1 v2 --> v1
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
boolean translation
example:
translate(test true s1 s2) = (\x.\y.\z.x y z) (\x.\y.x) v1 v2
(where v1 = translate s1
and v2 = translate s2)
in the source language we have:
test true s1 s2 --> s1
so in the target we want:
(\x.\y.\z.x y z) (\x.\y.x) v1 v2 --> v1
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
boolean translation
Theorem (Translation Preserves Semantics):
If
s1 --> s2 (in the lambda calculus with booleans)
then
(translate(s1)) --> (translate(s2)) (in the pure lambda calc)
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> _____________
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
((\x.\y.\z.x y z) (\x.\y.x)) v1) --> ___________
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> _____________ v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
e1
e1
e1’
booleans
(\x.\y.\z.x y z) (\x.\y.x) --> ___________
(\x.\y.\z.x y z) (\x.\y.x)) v1 --> ___________ v1
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> _____________ v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
(app1)
(b)
booleans
\x.\y.\z.x y z (\x.\y.x) --> \y.\z.x y z [\x.\y.x / x]
((\x.\y.\z.x y z) (\x.\y.x)) v1) --> v1
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
(app1)
(b)
booleans
\x.\y.\z.x y z (\x.\y.x) --> \y.\z.(\x.\y.x) y z
((\x.\y.\z.x y z) (\x.\y.x)) v1) --> v1
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
(app1)
(b)
booleans
\x.\y.\z.x y z (\x.\y.x) --> \y.\z.(\x.\y.x) y z
((\x.\y.\z.x y z) (\x.\y.x)) v1) --> (\y.\z.(\x.\y.x) y z) v1
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
(app1)
(b)
booleans
(\x.\y.\z.x y z) (\x.\y.x) --> \y.\z.(\x.\y.x)
((\x.\y.\z.x y z) (\x.\y.x)) v1) --> \y.\z.(\x.\y.x) v1
(((\x.\y.\z.x y z) (\x.\y.x)) v1) v2 --> \y.\z.(\x.\y.x) v1 v2
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
(app1)
(app1)
(b)
booleans
translate(true) = \t.\f. t
translate(false) = \t.\f. f
translate(and) = \b.\c. b c (translate(false))
translate(x) = ...
translate(and true true) = (\b.\c. b c (\t.\f.f)) (\t.\f.t) (\t.\f.t)
booleans
translate(true) = \t.\f. t
translate(false) = \t.\f. f
translate(and) = \b.\c. b c (translate(false))
translate(x) = ...
translate(and true true) = (\b.\c. b c (\t.\f.f)) (\t.\f.t) (\t.\f.t)
===> wow is that ever tough to read ...
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
translate(and true true)
= a tru tru
= (\b.\c. b c fls) tru trutarget languageexpression (ie: a and tru arejust meta-variablesI’m using to abbreviateand make morereadable the translatedterm)
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
a tru tru
= (\b.\c. b c fls) tru tru
--> (\c.tru c fls) tru
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
a tru tru
= (\b.\c. b c fls) tru tru
--> (\c.tru c fls) tru
--> tru tru fls
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
a tru tru
= (\b.\c. b c fls) tru tru
--> (\c.tru c fls) tru
--> tru tru fls
= (\t.\f. t) tru fls e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
a tru tru
= (\b.\c. b c fls) tru tru
--> (\c.tru c fls) tru
--> tru tru fls
= (\t.\f. t) tru fls
-->(\f. tru) fls e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
tru = \t.\f. t fls = \t.\f. f a = \b.\c. b c fls
a tru tru
= (\b.\c. b c fls) tru tru
--> (\c.tru c fls) tru
--> tru tru fls
= (\t.\f. t) tru fls
-->(\f. tru) fls
--> tru
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
if statements
e ::= x | v | e1 e2
| if e1 then e2 else e3
v ::= \x.e | true | false
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
if e1 then e2 else e3 --> if e1’ then e2 else e3 (if1)
if true then e2 else e3 --> e2 (if2)
e1 --> e1’
if false then e2 else e3 --> e3 (if3)
An Example
loop = (\x.x x) (\x.x x)
if (\x.x) true then \x.x else loop
--> if true then \x.x else loop
--> \x.x
booleans
• what is wrong with the following translation? translate true = tru
translate false = fls
translate (if e1 then e2 else e3)
= test (translate e1) (translate e2) (translate e3)
translate (\x.e) = \x.(translate e)
translate (e1 e2) = (translate e1) (translate e2)
booleans
• what is wrong with the following translation? translate true = tru
translate false = fls
translate (if e1 then e2 else e3)
= tst (translate e1) (translate e2) (translate e3)
...
-- e2 and e3 will both be evaluated regardlessof whether e1 is true or false-- the target program might not terminate in some cases when the source program would
pure lambda terms:tru = \t.\f.tfls = \t.\f.ftst = \x.\y.\z. x y z
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> tst tru (\x.x) ((\x.x x) (\x.x x))
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> tst tru (\x.x) ((\x.x x) (\x.x x))
(((\x.\y.\z. x y z) tru) (\x.x)) ((\x.x x) (\x.x x)) -->
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> tst tru (\x.x) ((\x.x x) (\x.x x))
(((\x.\y.\z. x y z) tru) (\x.x)) ((\x.x x) (\x.x x)) -->
((\y.\z. tru y z) (\x.x)) ((\x.x x) (\x.x x)) -->
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> test tru (\x.x) ((\x.x x) (\x.x x))
(((\x.\y.\z. x y z) tru) (\x.x)) ((\x.x x) (\x.x x)) -->
((\y.\z. tru y z) (\x.x)) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) -->
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> tst tru (\x.x) ((\x.x x) (\x.x x))
(((\x.\y.\z. x y z) tru) (\x.x)) ((\x.x x) (\x.x x)) -->
((\y.\z. tru y z) (\x.x)) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) -->
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
example
translate (if (\x.x) true then \x.x else loop)
= tst translate((\x.x) true) (translate(\x.x)) (translate(loop))
= tst ((\x.x) tru) (\x.x) (loop)
= tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x))
tst ((\x.x) tru) (\x.x) ((\x.x x) (\x.x x)) --> tst tru (\x.x) ((\x.x x) (\x.x x))
(((\x.\y.\z. x y z) tru) (\x.x)) ((\x.x x) (\x.x x)) -->
((\y.\z. tru y z) (\x.x)) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) -->
(( \z. tru (\x.x) z) ) ((\x.x x) (\x.x x)) --> ...
e1 --> e1’e1 e2 --> e1’ e2
e2 --> e2’v e2 --> v e2’
(\x.e) v --> e [v/x](b)
(app1)
(app2)
booleans
• we saw this translation didn’t work:translate (if e1 then e2 else e3)
= tst (translate e1) (translate e2) (translate e3)
• we need to delay execution of e2, e3 until the right time:translate (true) = \x.\y.(x (\x.x))
translate (false) = \x.\y.(y (\x.x))
translate (if e1 then e2 else e3)
= (\x.\y.\z. x y z) (translate e1) (\w.translate e2) (\w.translate e3)
... other cases ...
pairs
• would like to encode the operations– create e1 e2– fst p– sec p
• pairs will be functions– when the function is used in the fst or sec
operation it should reveal its first or second component respectively
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
fst (create tru fls)
= fst ((\x.\y.\b. b x y) tru fls)
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
fst (create tru fls)
= fst ((\x.\y.\b. b x y) tru fls)
-->* fst (\b. b tru fls)
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
fst (create tru fls)
= fst ((\x.\y.\b. b x y) tru fls)
-->* fst (\b. b tru fls)
= (\p.p tru) (\b. b tru fls)
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
fst (create tru fls)
= fst ((\x.\y.\b. b x y) tru fls)
-->* fst (\b. b tru fls)
= (\p.p tru) (\b. b tru fls)
--> (\b. b tru fls) tru
pairs
create = \x.\y.\b. b x y
fst = \p. p tru tru = \x.\y.x
sec = \p. p fls fls = \x.\y.y
fst (create tru fls)
= fst ((\x.\y.\b. b x y) tru fls)
-->* fst (\b. b tru fls)
= (\p.p tru) (\b. b tru fls)
--> (\b. b tru fls) tru
--> tru tru fls
= (\x.\y.x) tru fls
--> (\y.tru) fls
--> tru
and we can go on...
• numbers• arithmetic expressions (+, -, *,...)• lists, trees and datatypes• exceptions, loops, ...• ...• the general trick:
– values will be functions – construct these functions so that they return the appropriate information when called by an operation