CMSC330

Lambda Calculus

Lambda Calculus

Expression
Lambda Calc
Evaluation
Lambda Calc Bindings

Expression

Expression

Many ways to express ourselves

What's the minimum needed to do so?

Let's first consider: what do we need to express? Computation

Let's first consider: what do we need to express? Computation

FSM is not enough

We need a turing machine

Turing Machine: a machine that can compute a solution to any solvable problem

Our computers are universal turing machines

Turing Completeness: Something that can simulate a turing machine

Goal: find a minimal language that is turing complete

Goal: find a minimal language that is turing complete

Fun examples:

  • Minecraft
  • Microsoft Powerpoint
  • mov
  • Magic the gathering

Fun, but what about a language?

Lambda Calc

\(\lambda\)-calculus: a minimal turing complete language


e -> x
    |λx.e
    |e e
          
  • Where \(x\) is a varaible
  • Where \(\lambda x.e\) is a function definition
  • Where \(e\ e\) is a function call

e -> x
    |λx.e
    |e e
          

Convention:

  • Scope of λ extends right until end or parenthesis
  • Function application is left associative

e -> x
    |λx.e
    |e e
          

Convention:

  • Scope of λ extends right until end or parenthesis
    • λx.λy.x y = (λx.(λy.x y))
  • Function application is left associative
    • x y z = (x y) z

Evalutation

(λx.x) y means something


e -> x
    |λx.e
    |e e
          

(fun x -> x) y
          

Beta Reduction


y
          

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

Remember our scoping rules


(fun x -> fun y -> x y) x y
          

(fun a -> fun b -> a b) x y
          

Alpha Conversion

\(a,b\) are bound variables

\(x,y\) are free variables


e -> x
    |λx.e
    |e e
          

\(\frac{}{x \Rightarrow x}\) (where \(x\) is free)

\(\frac{}{\lambda x.e \Rightarrow \lambda x.e}\)

\(\frac{e1 \Rightarrow (\lambda x.e3)\qquad e2\Rightarrow e4 \qquad {x:e4};e3\Rightarrow e5}{e1\ e2 \Rightarrow e5}\)

\(\frac{e1 \Rightarrow x\qquad e2\Rightarrow e3}{e1\ e2 \Rightarrow x\ e3}\)

This actually is "big-step" semantics:
\(e\) will eventaully evaluate \(e'\)


e -> x
    |λx.e
    |e e
          

\(\frac{}{x \Downarrow x}\) (where \(x\) is free)

\(\frac{}{\lambda x.e \Downarrow \lambda x.e}\)

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad e2\Downarrow e4 \qquad {x:e4};e3\Downarrow e5}{e1\ e2 \Downarrow e5}\)

\(\frac{e1 \Downarrow x\qquad e2\Downarrow e3}{e1\ e2 \Downarrow x\ e3}\)

This actually is "big-step" semantics:
\(e\) will eventaully evaluate \(e'\)

\(\frac{}{x \Downarrow x}\) (where \(x\) is free)

\(\frac{}{\lambda x.e \Downarrow \lambda x.e}\)

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad e2\Downarrow e4 \qquad {x:e4};e3\Downarrow e5}{e1\ e2 \Downarrow e5}\)

\(\frac{e1 \Downarrow x\qquad e2\Downarrow e3}{e1\ e2 \Downarrow x\ e3}\)

This actually is "big-step" semantics:
\(e\) will eventaully evaluate \(e'\)

How does it eventually evaluate? Small step semantics

How does it eventually evaluate? Small step semantics

\(\frac{}{x \Rightarrow x}\) (where \(x\) is free)

\(\frac{e1 \Rightarrow e2}{\lambda x.e1 \Rightarrow \lambda x.e2}\)

\(\frac{e1 \Rightarrow e3}{e1\ e2 \Rightarrow e3\ e2}\)

\(\frac{e2 \Rightarrow e3}{e1\ e2 \Rightarrow e1\ e3}\)

\(\frac{}{(\lambda x.e1)\ e2 \Rightarrow \{x:e2\};e1}\)

Issue with order of evaluation

Issue with order of evaluation

Use one of the following to fix:

  • Eager (Call by value) evaluation
  • Lazy (Call by name) evaluation
  • Partial evaluation

Eager (Call by value) evaluation

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad e2\Downarrow e4 \qquad {x:e4};e3\Downarrow e5}{e1\ e2 \Downarrow e5}\)

\(\frac{e1 \Rightarrow e3}{e1\ e2 \Rightarrow e3\ e2}\)

\(\frac{e2 \Rightarrow e3}{e1\ e2 \Rightarrow e1\ e3}\)

\(\frac{e2 = (\lambda x.e3)}{(\lambda x.e1)\ e2 \Rightarrow \{x:(\lambda x.e3)\};e1}\)

\(\frac{e2 = y}{(\lambda x.e1)\ e2 \Rightarrow \{x:y\};e1}\)

Eager (Call by value) evaluation

\(\frac{e1 \Rightarrow e3}{e1\ e2 \Rightarrow e3\ e2}\)

\(\frac{e2 \Rightarrow e3}{e1\ e2 \Rightarrow e1\ e3}\)

\(\frac{e2 = (\lambda x.e3)}{(\lambda x.e1)\ e2 \Rightarrow \{x:(\lambda x.e3)\};e1}\)

\(\frac{e2 = y}{(\lambda x.e1)\ e2 \Rightarrow \{x:y\};e1}\)

Issue: Lambda calc is left associative

Eager (Call by value) evaluation

\(\frac{e1 \Rightarrow e3}{e1\ e2 \Rightarrow e3\ e2}\)

\(\frac{e1 = x \text{ or }e1 = (\lambda x.e3)\qquad e2 \Rightarrow e3}{e1\ e2 \Rightarrow e1\ e3}\)

\(\frac{e2 = (\lambda x.e3)}{(\lambda x.e1)\ e2 \Rightarrow \{x:(\lambda x.e3)\};e1}\)

\(\frac{e2 = y}{(\lambda x.e1)\ e2 \Rightarrow \{x:y\};e1}\)

Issue: Lambda calc is left associative

Lazy (Call by name) evaluation

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad e2\Downarrow e4 \qquad {x:e4};e3\Downarrow e5}{e1\ e2 \Downarrow e5}\)

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad {x:e2};e3\Downarrow e4}{e1\ e2 \Downarrow e4}\)

Lazy (Call by name) evaluation

\(\frac{e1 \Downarrow (\lambda x.e3)\qquad {x:e2};e3\Downarrow e4}{e1\ e2 \Downarrow e4}\)

\(\frac{e1 \Rightarrow e3}{e1\ e2 \Rightarrow e3\ e2}\)

\(\frac{}{(\lambda x.e1)\ e2 \Rightarrow \{x:e2\};e1}\)

Partial Evaluation

Useful when compiling

Evaluate what you can that does not change meaning before doing more

λy.(λz.z) y x

λy.y x

Lambda Calc Bindings

We said Lambda Calculus was a turing complete language

Let's encode some values to λ expressions

  • true: λx.λy.x
  • false: λx.λy.y
  • if a then b else c: a b c
  • if true then false else true

if true then false else true

  • true: λx.λy.x
  • false: λx.λy.y
  • if a then b else c: a b c

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

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

(λx.λy.y)

if true then false else true

  • true: λx.λy.x
  • false: λx.λy.y
  • if a then b else c: a b c
  • not: λx.x false true ((λx.x) (λx.λy.y) (λx.λy.x))
  • and: λx.λy.x y false ((λx.λy.x y (λx.λy.y)))
  • or: λx.λy.x true y ((λx.λy.x (λx.λy.x) y))

We can also encode pairs, numbers, and more