<<

Untyped λ -

Faridah Akinotcho, Lily Bryant, Junze Wu Outline

● History

● Construction and reductions

● Encoding data types and structures

and the Y combinator

● Variants and influence Historical Figures Why λ? λ Formal Description Definition of λ-terms

Assume infinite set of variables V = {x, y, z, …}.

Set Λ of λ-terms: () If u ∊ V, then u ∊ Λ. (Application) If M and N ∊ Λ, then (M N) ∊ Λ. (Abstraction) If u ∊ V and M ∊ Λ, then (λu.M) ∊ Λ.

Example:

((λx.x) (λy.(y z))) Terminology: Scoping and Boundness

Free Variables Bound Variables

FV: Λ ➝ �(V) BV: Λ ➝ �(V) (Variable) FV(x) = x (Variable) BV(x) = ∅ (Abstraction) FV(λx.M) = FV(M) \ {x} (Abstraction) BV(λx.M) = {x} ∪ BV(M) (Application) FV(M N) = FV(M) ∪ FV(N) (Application) BV(M N) = BV(M) ∪ BV(N)

➡ A λ- M is closed if FV(M) = ∅. M is also called a combinator. Terminology:

Given a λ-term M, we denote the substitution of a variable x in M by N as M[x:=N] such that:

● x[x:=N] = N

● y[x:=N] = y if x ≠ y

● (PQ)[x:=N] = (P[x:=N])(Q[x:=N])

● (λy.P)[x:=N] = λz.(Pʸᶻ[x:=N]) where Pʸᶻ stands for P with every instance of y renamed to z, such that z ∉ FV(N) Terminology:

A common shorthand is to use multi- functions. These can be rewritten as nested single-argument functions where each “level” takes an argument and returns another .

Examples: (λx y.(x y)) ≣ (λx.(λy.(x y)))

((λx y.(x y)) 5) ≣ ((λx.(λy.(x y))) 5) →ᵦ (λy.(5 y)) “” Reductions

● α-conversion: Argument renaming in functions

● β-reduction: with substitution ● η-conversion: Function equivalence Reductions: �-conversion

Let M ∊ Λ. �-conversion performs the following renaming, provided y ∉ FV(M) and y ∉ BV(M):

λx.M =� λy.(M[x:=y])

➡ λx.x and λz.z are �-equivalent, but not syntactically-equivalent. Reductions: β-reduction Reductions: β-reduction terminology

➡ The left hand side is called a redex and the right hand side is the contractum.

➡ If P →ᵦ L, then P and L are said to be β-equivalent, denoted P =ᵦ L. Reductions: β-reduction terminology

➡ M is in β-normal form (or β-nf) if M does not contain a redex.

➡ M is weakly-normalizable if there exists some N in β-nf where M ↠ᵦ N.

➡ M is strongly-normalizable if there does not exist an infinite reduction path from M to N. Reductions: β-reduction

Church-Rosser

λ-calculus is confluent under β-reductions, i.e. supposing M, M1, M2, L ∊ Λ,

If M ↠ᵦ M1 and M ↠ᵦ M2, then there exists some L such that M1 ↠ᵦ L and M2 ↠ᵦ L.

Consequences:

➡ A λ-term has at most one normal form. ➡ Ordering of reduction choice does not matter (non-deterministic reduction!). This even applies in many typed versions of the calculus. Reductions: β-reduction theorems

A set L ⊆ Λ is closed under β-conversion if ∀M, N ∊ Λ, ((M ∊ L ∧ M =ᵦ N) ⇒ N ∊ L).

Scott-Curry Theorem If two non-empty, disjoint sets of λ-terms are closed under β- conversion,

then they are recursively inseparable.

Consequence:

➡ Showing two non-empty λ-terms are β-equivalent is undecidable. Reductions: η-conversion

If function F takes its argument and immediately applies the argument to G, then F is functionally-equivalent to G.

λx.(M x) ⟶η M where x ∉ FV(M)

➡ Intuitively: two functions are identical if they do the same thing. Encoding data types and structures

Boolean Logic

Truth values With these two terms, we can define:

TRUE := λx y. x NOT := λp. ((p FALSE) TRUE) AND := λp q. ((p q) p) FALSE := λx y. y OR := λp q. ((p p) q)

IFTHENELSE := λc t e. (( t) e))

Church numerals Peano numbers ZERO := λf x. x A NATURAL is one of: ONE := λf x. (f x) ● ZERO TWO := λf x. (f (f x)) ● SUCC NATURAL THREE := λf x. (f (f (f x))) … SUCC := λn f x. (f ((n f) x)) n := λf x. f n x

Elements needed: successor, predecessor, addition, subtraction, multiplication, division, .

Immediately, we can define: PLUS:= λm n. ((m SUCC) n) MULT := λm n. ((m (PLUS n)) ZERO) Alternatively, MULT := λm n f. (m (n f)) EXP := λm n. (n m) Pairs and Lists

For predecessor and subtraction, we first need to introduce pairs:

Encoding pairs and lists := (λa b s.((s a) b)) CAR := (λp.(p TRUE)) CDR := (λp.(p FALSE))

NIL := FALSE Arithmetic (cont.)

The “wisdom tooth trick”: T := (λp.((CONS (SUCC (CAR p))) (CAR p))))) PRED := (λn.(CDR ((n T) ((CONS ZERO) ZERO))))

SUB := (λm n.(n PRED) m))

Note: PRED ZERO is ZERO Predicates

ZERO? :=λn.((n (λx. FALSE)) TRUE) LEQ? := λm n.ZERO?((SUB m) n) GT? := λm n.NOT ((LEQ? m) n) EQ? := λm n.((AND ((LEQ? m) n)) ((LEQ? n) m))) Named Constants

We can introduce let , with the following relation: LET x = n IN m ≣ ((λx.m) n) Arithmetic (cont.)

Division is a recursive procedure: (define (divide n m) (if (>= n m) (+ 1 (divide (- n m) m)) 0)) But we don’t have a way to do recursion yet... Recursion Y Combinator An example, the function

#lang racket (define factorial (λ (n) (if (zero? n) 1 (* n (factorial (sub1 n)))))) ;; Sadly, we can’t do this in λ-calculus An example, the factorial function

#lang racket (define almost-factorial (λ (f) What function should we pass in for f (λ (n) in order to get the actual factorial function back? (if (zero? n) It is the actual factorial function that we 1 are trying to define! (* n (f (sub1 n))))))) An example, the factorial function

So the f that we are looking for is a “fixed-point” of almost-factorial: (almost-factorial f) = f Fixed-point

A function has a fixed point at a if f(a) = a. Function f applied to a returns a again: “Fixed” by f. Examples (functions defined on real numbers): f(n) = n2 has two fixed points: 0 and 1 f(n) = n + 1 has no fixed points

f(f(f ...f(f(f(f(a))...) = a Fixed-point theorem

For all L ∈ Λ there is M ∈ Λ such that (L M) =ᵦ M. Proof:

For given L, define M := ((λx.(L(x x))) (λx.(L(x x)))).

This M is a redex, so we have:

M ≡ ((λx. L(x x))(λx. L(x x))) →ᵦ L(((λx. L(x x)) (λx. L(x x)))) ≡ (L M).

Hence, (L M) =ᵦ M. Recursion: Y combinator

Fixed-point combinator:

Y := λf.(λx.(f (x x)) λx.(f (x x)))

Y is a higher order function that computes the fixed-point of the argument function. For any λ-term f, (Y f) is a fixed point of f: (Y f) = (f (Y f)) An example, the factorial function

#lang lazy (define Y (λ (f) ((λ (x) (f (x x))) (λ (x) (f (x x)))))) (define factorial (Y (λ (f) (λ (n) (if (zero? n) 1 (* n (f (sub1 n)))))))) An example, the factorial function

#lang lazy (define Y (λ (f) ((λ (x) (f (x x))) (λ (x) (f (x x)))))) (define FACTORIAL (Y (λ (f) (λ (n) (((ZERO? n) ONE) ((MULT n) (f (PRED n)))))))) Division

(define divide (Y (λ (f) (λ (n) (λ (m) (if (>= n m) (add1 ((f (- n m)) m)) 0)))))) Variants and Influence Variants in Programming Reduction Strategies

We define a strategy as a function S, S: Λ → Λ If S(M) = N, then M →ᵦ N. Reduction Strategies

Full Beta Reductions : Any redex can be reduced at any time

Applicative Order Reduction : The rightmost, innermost term is always evaluated first, i.e. the to a function are always evaluated first It is a call-by-value .

((�x.M) (�y.P)) Reduction Strategies

Normal Order Reduction : The leftmost, outermost redex is always reduced first, i.e. whenever possible the arguments are substituted into the body of an abstraction before they are reduced.

(((�x.M) N) (�y.P))

It is similar to call-by-name strategy except reductions can happen in the body of an abstraction, ex:

λx.(λx.x)x is in normal form according to the call-by-name strategy, but not the normal order since it contains the redex (λx.x)x Reduction Strategies: an example

We define omega, a combinator Ω=((λx.(xx))(λx.(xx)))

Let M:=(�u.v) Ω

There is an infinite reduction by contracting Ω and a one step reduction, in other words M is weakly normalizing. Typed λ-calculus

● λ-calculus and its variants provide the theoretical foundation for functional languages such as Lisp, ML, and Scheme. ● is a typed λ-calculus that formed the basis for some typed functional languages, such as Haskell and OCaml, and define polymorphism: the idea allowing of generic type variables. ● Anonymous functions and other aspects of functional programming have also been introduced into many non-functional languages, such as Java, C, and MATLAB. Variants in Logic De Bruijn Indices

Alternative to Church’s notation which removes the overhead of naming variables.

Each variable becomes a natural equal to the number of variables/lambdas introduced between its definition and usage (inclusive).

Example:

((�x.�y.�z. w y x z) (�u.�v.v u)) ((� � � 4 2 3 1) (� � 1 2))

w is a free variable

➡ α-equivalent (renamed) terms are now syntactically-equivalent SKI calculus

S: (S x y z) ≣ (λx y z.((x z) (y z))) →ᵦ (x z (y z))

K: (K x y) ≣ (λx y.x) →ᵦ x

I: (I x) → � ((S K K) x) →ᵦ x

➡ For all M ∊ Λ, there exists a combination of S and K that is functionally-equivalent to M. S and K form the basis of all λ-terms. ➡ Essentially, a tiny Turing-complete language!

was developed around the same time as λ-calculus and works with this idea of combinators (without abstraction) as a basis for reasoning. Conclusion

�-calculus is..

● A simple way of capturing while still providing many powerful results ● Very helpful for building up the logical basis of functional reasoning ● Less helpful for finding intuition on very high level descriptions of

(Book) Church, A. (1941). The calculi of lambda-conversion.

(Book) Barendregt, H.P. (1984) .The Its Syntax and Semantics.

(Paper) Barendregt, H.P. (1997). The Impact of the Lambda Calculus in Logic and .

(Paper) Plotkin, G.D. (1974). Call-by-Name, Call-by-Value, and The Lambda Calculus.

(Course notes, chapter 4) Felleisen, M & Flatt, M. (2007). Programming Languages and Lambda Calculi.

(Paper) Felleisen, M. & Friedman, D. P .(1989). A Syntactic Theory of Sequential State.

(Paper) Moggi, E. (1989). Computational lambda-calculus and monads.

(Book) Barendregt, H. P. & Dekkers, W., Statman, R. (2013). Lambda calculus with types.

(Book) Nederpelt, R. & Geuvers, H. (2014). and Formal Proofs.

(Screencast) Lambda Calculus: PyCon 2019 Tutorial