CS 611: Lecture 10 More Lambda Calculus September 20, 1999 Cornell University Computer Science Department Andrew Myers normal form call-by-name/normal order: s-s op.sem. call-by-value/applicative order: s-s op.sem Church-Rosser theorem why is call-by-name hard to implement? de Bruijn indices combinators
Why is substitution hard? Substitution on lambda expressions: (l y e0) [e1 / x ] (l y’ e0[y’/y][e1/x ]) where y’ FV e0 y’ FV e1 Abstract syntax DAGs without names: apply l (e0 e1) (l x e) e0 e1 e var CS 611—Semantics of Programming Languages—Andrew Myers
Example (l y e0) [e1 / x ] (l y’ e0[y’/y][e1/x ]) On expressions: (l y e0) [e1 / x ] (l y’ e0[y’/y][e1/x ]) (l a (b (l b a))) [ (l a a) / b ] = (l a’ (b (l b a’)) [(l a a)/ b]) = (l a’ (b (l b a’)) [(l a a) / b]) = (l a’ ((l a a) (l b a’))) On graphs: l l ... ... apply apply l var l var var l l var var var var var CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers Holes in scope Reuse of an identifier creates a hole in scope (l a ((b (l a (b a))) a)) scope of outer “a” Variable is inaccessible within the region in which it is shadowed Common source of programming errors CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers Reductions Lambda calculus reductions alpha (change of variable) (l x e) (l x’ e[x’/x]) if (x’ FV e) beta (application) (( x e1) e2) e1[e2 / x] eta (removal of extra abstraction) (l x (e x)) e if (x FV e) Expressions are equivalent if they have the same Stoy diagram/abstract DAG can be converted to each other using alpha renaming on sub-expressions Evaluation is a sequence of reductions a b h CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers Normal order Currently defined operational semantics: lazy evaluation (call-by-name) e0 (l x e2) (e0 e1) e2 [ x / e1 ] Normal order evaluation: apply b (or h) reductions to leftmost redex till no reductions can be applied (normal form) Always finds a normal form if there is one Substitutes unevaluated form of actual parameters Hard to understand, implement with imperative lang. CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers Applicative order Only b-substitute when the argument is fully reduced: argument evaluated before call e1 1 e’1 (e0 e1) 1 (e0 e’1) e0 1 e’0 (e0 v) 1 (e’0 v) ((l x e) v) 1 e[v/x] Almost call-by-value CS 611—Semantics of Programming Languages—Andrew Myers
Applicative order Applicative order may diverge even when a normal form exists Example: ((b c) ((a (a a)) (a (a a)))) Need special non-strict if form: (IF TRUE 0 Y) What if we allow any arbitrary order of evaluation? CS 611—Semantics of Programming Languages—Andrew Myers
Non-deterministic evaluation e0 1 e’0 (e0 e1) 1 (e’0 e1) e 1 e’ (l x e) 1 (l x e’) e1 1 e’1 (e0 e1) 1 (e0 e’1) (( x e1) e2) 1 e1[e2 / x] (b) x FV e (l x (e x)) 1 e (h) CS 611—Semantics of Programming Languages—Andrew Myers
Church-Rosser theorem Non-determinism in evaluation order does not result in non-determinism of result Formally: (e0 * e1 e0 * e2 ) e3 . e1 * e3 e2 * e’3 e3 = e’3 Implies: only one normal form for an expression Transition relation has the Church-Rosser property or diamond property if this theorem is true e0 e1 e2 e3 a CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers Concurrency Transition rules for application permit parallel evaluation of operator and operand Church-Rosser: any interleaving of computation yields same result Many commonly-used languages do not have Church-Rosser property C: int x=1, y = (x = 2)+x Intuition: lambda calculus is functional; value of expression determined locally (no store) e1 1 e’1 (e0 e1) 1 (e0 e’1) e0 1 e’0 (e0 e1) 1 (e’0 e1) CS 611—Semantics of Programming Languages—Andrew Myers
Simplifying lambda calculus Can we capture essential properties of lambda calculus in an even simpler language? Can we get rid of (or restrict) variables? S & K combinators: closed expressions are trees of applications of only S and K (no variables or abstractions!) de-Bruijn indices: all variable names are integers CS 611—Semantics of Programming Languages—Andrew Myers
CS 611—Semantics of Programming Languages—Andrew Myers DeBruijn indices Idea: name of formal argument of abstraction is not needed e ::= l e0 | e0 e1 | n Variable name n tells how many lambdas to walk up in AST IDENTITY (l a a) = (l 0) TRUE (l x (l y x)) = (l (l 1)) FALSE = 0 (l x (l y y)) = (l (l 0)) 2 (l f (l a (f (f a))) = (l (l (1 (1 0)))) CS 611—Semantics of Programming Languages—Andrew Myers
Translating to DeBruijn indices A function DB e that compiles a closed lambda expression e into DeBruijn index representation (closed = no free identifiers) Need extra argument N : symbol integer to keep track of indices of each identifier DB e = T e, Ø T (e0 e1), N = (T e0 , N T e1 , N) T x , N = N(x) T (l x e) , N = (l T e, (l y . if x = y then 0 else 1+N(y))) CS 611—Semantics of Programming Languages—Andrew Myers