Why formalize? ! ML is tricky, particularly in corner cases Formal Semantics ! generalizable type variables? ! polymorphic references? ! exceptions? ! Some things are often overlooked for any language ! evaluation order? side-effects? errors? ! Therefore, want to formalize what a language's definition really is ! Ideally, a clear & unambiguous way to define a language ! Programmers & compiler writers can agree on what's supposed to happen, for all programs ! Can try to prove rigorously that the language designer got all the corner cases right 1 2 Aspects to formalize Approach ! Syntax : what's a syntactically well-formed program? ! Formalizing full-sized languages is very hard, ! EBNF notation for a context-free grammar tedious ! Static semantics : which syntactically well-formed ! many cases to consider programs are semantically well-formed? which ! lots of interacting features programs type-check? ! Better: boil full-sized language down into ! typing rules, well-formedness judgments essential core , then formalize and study the ! Dynamic semantics : what does a program core evaluate to or do when it runs? ! operational, denotational, or axiomatic semantics ! cut out as much complication as possible, without ! Metatheory : properties of the formalization itself losing the key parts that need formal study ! E.g. do the static and dynamic semantics match? i.e., ! hope that insights gained about core will carry is the static semantics sound w.r.t. the dynamic semantics? back to full-sized language 3 4 The lambda calculus Untyped λ -calculus: syntax ! The essential core of a (functional) ! (Abstract) syntax: programming language e ::= x variable ! The tiniest Turing-complete programming | λ x . e function/abstraction language ( ≅ fn x => e ) ! Outline: | e 1 e 2 call/application ! Untyped: syntax, dynamic semantics, cool ! Freely parenthesize in concrete syntax to imply properties the right abstract syntax ! Simply typed: static semantics, soundness, more ! The trees described by this grammar are cool properties called term trees ! Polymorphic: fancier static semantics 5 6 1
α -renaming Free and bound variables ! λ x . e binds x in e ! First semantic property of lambda calculus: bound variables in a term tree can be ! An occurrence of a variable x is free in renamed (properly) without affecting the e if it's not bound by some enclosing semantics of the term tree lambda ! α -equivalent term trees freeVars( x ) ≡ x ! ( λ x 1 . x 2 x 1 ) ⇔ α ( λ x 3 . x 2 x 3 ) freeVars( λ x . e ) ≡ freeVars( e ) – { x } ! cannot rename free variables freeVars( e 1 e 2 ) ≡ freeVars( e 1 ) ∪ freeVars( e 2 ) ! term e : e and all α -equivalent term trees ! e is closed iff freeVars( e ) = {} ! Can freely rename bound vars whenever helpful 7 8 Evaluation: β -reduction Examples ! Define what it means to "run" a lambda- calculus program by giving simple reduction/rewriting/simplification rules ! " e 1 → β e 2 " means " e 1 evaluates to e 2 in one step" ! One case: ! ( λ x . e 1 ) e 2 → β [ x → e 2 ] e 1 ! "if you see a lambda applied to an argument expression, rewrite it into the lambda body where all free occurrences of the formal in the body have been replaced by the argument expression" 9 10 Substitution Result of reduction ! When doing substitution, must avoid ! To fully evaluate a lambda calculus term, i.e., changing the meaning of a variable to determine the meaning of a term, simply occurrence perform β -reduction until you can't any more ! → β * ≡ reflexive, transitive closure of → β [ x → e ] x ≡ e [ x → e ] y ≡ y , if x ≠ y ! When you can't any more, you have a value , [ x → e ]( λ x . e 2 ) ≡ ( λ x . e 2 ) which is a normal form of the input term [ x → e ]( λ y . e 2 ) ≡ ( λ y . [ x → e ] e 2 ), if x ≠ y ! Does every lambda-calculus term have a normal and y not free in e form? [ x → e ]( e 1 e 2 ) ≡ ([ x → e ] e 1 ) ([ x → e ] e 2 ) ! use α -renaming to ensure " y not free in e " 11 12 2
Reduction order Two reduction orders ! Can have several lambdas applied to an ! Normal-order reduction argument in one expression (a.k.a. call-by-name, lazy evaluation) ! Each called a redex ! reduce leftmost, outermost redex ! Therefore, several possible choices in ! Applicative-order reduction reduction (a.k.a. call-by-value, eager evaluation) ! Which to choose? ! reduce leftmost, outermost redex ! Does it matter? whose argument is in normal form ! To the final result? ! To how long it takes to compute? ! To whether the result is computed at all? 13 14 Amazing fact #1: Existence of normal forms? Church-Rosser Theorem, Part 1 * e 2 and e 1 → β * e 3 , then ! Thm. If e 1 → β ! Does every term have a normal form? * e 4 and e 3 → β * e 4 ∃ e 4 such that e 2 → β ! Corollary. Every term has a unique ! Consider: ( λ x . x x ) ( λ x . x x ) normal form, if it has one ! No matter what reduction order is used! ! Wow! 15 16 Amazing fact #2: Church-Rosser Theorem, Part 2 ! If a term has a normal form, then normal-order reduction will find it! ! Applicative-order reduction might not! ! Example: ! ( λ x 1 . ( λ x 2 . x 2 )) (( λ x . x x ) ( λ x . x x )) 17 3
Recommend
More recommend