200 likes | 228 Views
PPL. Applicative and Normal Form Verification, Type Checking and Inference. Applicative order vs. Normal Order Evaluation. To Evaluate a combination: (other than special form) Evaluate all of the sub-expressions in any order Apply the procedure that is the value of
E N D
PPL Applicative and Normal Form Verification, Type Checking and Inference
Applicative order vs. Normal OrderEvaluation To Evaluate a combination: (other than special form) Evaluate all of the sub-expressions in any order Applythe procedure that is the value of the leftmost sub-expression to the arguments (the values of the other sub-expressions)
Applicative order evaluation rules Combination... (<operator> <operand1> …… <operand n>) • Evaluate <operator> to get the procedure and evaluate <operands> to get the arguments • If <operator> is primitive: do whatever magic it does • If <operator> is compound: evaluate body with formal parameters replaced by arguments
Normal order evaluation Combination … (<operator> <operand1> …… <operand n>) • Evaluate <operator> to get the procedure and evaluate <operands> to get the arguments • If <operator> is primitive: do whatever magic it does • If <operator> is compound: evaluate body with formal parameters replaced by arguments
The Difference Normal ((lambda (x) (+ x x)) (* 3 4)) (+ (* 3 4) (* 3 4)) (+ 12 12) 24 Applicative ((lambda (x) (+ x x)) (* 3 4)) (+ 12 12) 24 This may matter in some cases: ((lambda (x y) (+ x 2)) 3 (/ 1 0)) Scheme is an Applicative Order Language!
Using let to define functions • Can we use let to define functions? • What about recursive functions?
Type Checking and Inference • Based on S. Krishnamurthi. Programming Languages: Application and Interpretation 2007. Chapters 24-26
Verification • Type correctness • Verify that the types of expressions in the program are “correct” • E.g. + is applied to numbers • In other languages: we should also check that the type of value stored in a variable correspond to the variable declared type • Program Verification • Verify that the program halts and produces the “correct” output • Somewhat easier with design-by-contract, where it can be done in a modular fashion
Languages and Types • Fully typed • C, Pascal, Java.. • Semi-typed • Scheme • Untyped • Prolog • Well-typing rules • Define relationships between types
Type Checking and Inference Type Checking. Given an expression, and a “goal” type T, verify that the expression type is T Example: Given the expression (+ (f 3) 7), we need to verify that (f 3) is a number Type Inference. Infer the type of an expression Example: (define x (f 3))
Types in Scheme • Numbers, booleans, symbols… • Union: • No value constructor • Type Constrcutor is union • Simplification rules • S union S = S • S union T = T union S • Unit Type • “Void”
Procedures and Type Polymorphism • What is the type of: • (lambda (x) x) • (lambda (f x) (f x)) • (lambda (f x) ( (f x) x)) • Instantiations, type variables renaming... • Next we construct a static type inference system
Type assignment and Typing statement • Type assignment • Mapping variables to types • Example: TA= {x<-Number, y<-[Number –> T]} • Notation: TA(x) = Number • Typing statement • TA |- e:T • Under TA, the expression e has the type T • {x<-Number} |- (+ x 5):Number • Type variables (as well as unbound variables)used in such statements are defined to be universally quantified • {x<-[T1 –> T2]} |- (x y):T2
Type assignment extension {x<-Number, y<-[Number –> T]}°{z<-Boolean} = {x<-Number, y<-[Number –> T], z<-Boolean} EMPTY° {x1<-T1, ..., xn<- Tn} = {x1<-T1, ..., xn<- Tn} Extension pre-condition: new variables are different from old ones.
Restricted Scheme (syntax) <scheme-exp> -> <exp> <exp> -> <atomic> | <composite> <atomic> -> <number> | <boolean> | <variable> <composite> -> <special> | <form> <number> -> Numbers <boolean> -> ’#t’ | ’#f’ <variable> -> Restricted sequences of letters, digits, punctuation marks <special> -> <lambda> | <quote>
<form> -> ’(’ <exp>+ ’)’ <lambda> -> ’(’ ’lambda’ ’(’ <variable>* ’)’ <exp>+ ’)’ <quote> -> ’(’ ’quote’ <variable> ’)’
Typing axioms • Typing axiom Boolean : For every type assignment TA and boolean b: TA |- b:Boolean Typing axiom Variable : For every type assignment TA and variable v: TA |- v:TA(v) Typing axioms Primitive procedure : TA |- +:[Number* ... *Number -> Number] TA |- not:[S -> Boolean] where S is a type variable. For every type assignment TA: TA |- display:[S -> Unit] S is a type variable. That is, display is a polymorphic primitive procedure.
Cont. • Typing rule Procedure : If TA{x1<-S1, ..., xn<-Sn} |- bi:Ui for all i=1..m, Then TA |- (lambda (x1 ... xn) b1 ... bm):[S1*...*Sn -> Um] Parameter-less Procedure: If TA |- bi:Ui for all i=1..m, Then TA |- (lambda ( ) b1 ... bm):[Unit -> Um] Typing rule Application : If TA |- f:[S1*...*Sn -> S], TA |- e1:S1, ..., TA |- en:Sn Then TA |- (f e1 ... en):S
Expression Trees The nesting of expressions can be viewed as a tree Sub-trees correspond to composite expressions Leaves correspond to atomic ones.
Type Inference Algorithm Algorithm Type-derivation: Input: A language expression e Output: A type expression t or FAIL Method: 1. For every leaf sub-expression of e, apart from procedure parameters, derive a typing statement by instantiating a typing axiom. Number the derived typing statements. 2. For every sub-expression e’ of e (including e): Apply a typing rule whose support typing statements are already derived, and it derives a typing statement for e’. Number the newly derived typing statement. 3. If there is a derived typing statement for e of the form e:t, Output = t. Otherwise, Output = FAIL