Apply

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
the leftmost sub-expression to the arguments
(the values of the other sub-expressions)
2
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
3
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
4
The Difference
Normal
Applicative
((lambda (x) (+ x x))
(* 3 4))
(+ 12 12)
24
((lambda (x) (+ x x))
(* 3 4))
(+ (* 3 4) (* 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!
5
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