PLAI Types

28
Dr. Philip Cannata PLAI Types Chapters 24 – 30 Types, Type Judgments, Type Systems and Type Safety - Chapters 24-28 Type Inference – Chapter 30

description

PLAI Types. Chapters 24 – 30 Types, Type Judgments, Type Systems and Type Safety - Chapters 24-28 Type Inference – Chapter 30. Introduction. (+ 3 ( define add3 (lambda (x) (+ x 3)))) Welcome to DrScheme , version 4.2.1 [3m]. Language: PLAI Scheme; memory limit: 256 megabytes. - PowerPoint PPT Presentation

Transcript of PLAI Types

Page 1: PLAI Types

Dr. Philip Cannata 1

PLAI Types

Chapters 24 – 30Types, Type Judgments, Type Systems and Type Safety - Chapters 24-28

Type Inference – Chapter 30

Page 2: PLAI Types

Dr. Philip Cannata 2

Introduction(+ 3 (define add3 (lambda (x) (+ x 3))))Welcome to DrScheme, version 4.2.1 [3m].Language: PLAI Scheme; memory limit: 256 megabytes.. define: not allowed in an expression context in: (define add3 (lambda (x) (+ x 3)))>(define mystery true)(+ 3 (if mystery 5 (define add3 (lambda (x) (+ x 3)))))Welcome to DrScheme, version 4.2.1 [3m].Language: PLAI Scheme; memory limit: 256 megabytes.. define: not allowed in an expression context in: (define add3 (lambda (x) (+ x 3)))>

Page 3: PLAI Types

Dr. Philip Cannata 3

IntroductionA type is any property of a program that we can establish without executing the program. In particular, types capture the intuition that we would like to predict a program’s behavior without executing it.. . .A type labels every expression in the language, recording what kind of value evaluating that expression will yield. That is, types describe invariants that hold for all executions of a program. They approximate this information in that they typically record only what kind of value the expression yields, not the precise valueitself.. . .Note that we are careful to refer to valid programs, but never correct ones. Types do not ensure the correctness of a program. They only guarantee that the program does not make certain kinds of errors.

Page 4: PLAI Types

Dr. Philip Cannata 4

Types, Type Judgments and Type Systems

A type system is a collection of types, the corresponding type judgments that ascribe types to expressions, and an algorithm

for performing this ascription.

Page 5: PLAI Types

Dr. Philip Cannata 5

Type Judgments

A type system is a collection of rules, known formally as type judgments, which describe how to determine the type of an expression. There must be at least one type rule for every kind of syntactic construct so that, given a program, at least one type rule applies to every sub-term. Judgments are often recursive, determining an expression’s type from the types of its parts.

Examples:Any numeral n has type number - n : numberAny function fun has type function – (define fun (i) b) : function

But what is the type of an identifier? Clearly, we need a type environment (a mapping from identifiers to types). It’s conventional to use (the upper-case Greek “gamma”) for the type environment. All type judgments will have the following form: |- e : twhere e is an expression and t is a type, which we read as “ proves that e has type t”. Thus,

|- n : number |- {fun {i} b} : function |- i : (i)

Page 6: PLAI Types

Dr. Philip Cannata 6

Type Judgments

Type Judgment Pseudo Prolog

|- L : number |- R : number

|- (+ L R) : number

number((+, L, R)) :- number(L), number(R).

|- f : ( 2) |- a : 1

|- (f a) : 2

someType((f a), Y) :- function(f, someType(X), someType(Y)), someType(a, X).

[i ] |- b : 2

|- fun {i : } : 2 b : ( 2)

|- c : boolean |- t : |- e :

|- (if c t e) :

True in Hmm?

Func

tion

App

licat

ion

Func

tion

Dec

lara

tion

Note:By the way, it would help to understand the status of terms like i and b and n in these judgments. They are “variable” in the sense that they will be replaced by some program term: for instance, {fun {i : t1} : t2 b} may be instantiated to {fun {x : number} : number x}, with i replaced by x, and so forth. But they are not program variables; rather, they are variables that stand for program text (including program variables). They are therefore called metavariables.

Page 7: PLAI Types

Dr. Philip Cannata 7

Function Declaration and Application

There is an important relationship between the type judgments for function declaration and for application:• When typing the function declaration, we assume the argument will have the right type and guarantee that the body, or result, will have the promised type.• When typing a function application, we guarantee the argument has the type the function demands, and assume the result will have the type the function promises. This interplay between assumptions and guarantees is quite crucial to typing functions. The two “sides” are carefully balanced against each other to avoid fallacious reasoning about program behavior. In addition, just as number does not specify which number will be used, a function type does not limit which of many functions will be used. If, for instance, the type of a function is (number -> number), the function could be either increment or decrement (or a lot else, besides). The type checker is able to reject misuse of any function that has this type without needing to know which actual function the programmer will use.

Page 8: PLAI Types

Dr. Philip Cannata 8

Type Judgments

|- c : boolean |- t : |- e :

|- (if c t e) :

Welcome to DrScheme, version 4.2.1 [3m].Language: PLAI Scheme; memory limit: 256 megabytes.> (if true ((lambda (x) 'x) 5) ((lambda (x) x) 1))'x> (if false ((lambda (x) 'x) 5) ((lambda (x) x) 1))1>

Lisp

Page 9: PLAI Types

Dr. Philip Cannata 9

Type Judgments

|- c : boolean |- t : |- e :

|- (if c t e) :

Haskell

$ haskell if.hs

Haskell 98 mode: Restart with command line option -98 to enable extensions

Main> :t myifmyif :: Bool -> a -> a -> aMain> myif True ((\ x -> 1) 5) ((\ x -> 1) 5)1Main> myif True ((\ x -> 1) 5) ((\ x -> "a") 5)ERROR - Cannot infer instance*** Instance : Num [Char]*** Expression : myif True ((\x -> 1) 5) ((\x -> "a") 5)

Main> :t myiftmyift :: Bool -> a -> a -> aMain> myift True ((\ x -> 1) 5) ((\ x -> 1) 5)1Main> myift True ((\ x -> 1) 5) ((\ x -> "a") 5)ERROR - Cannot infer instance*** Instance : Num [Char]*** Expression : myift True ((\x -> 1) 5) ((\x -> "a") 5)

$ cat if.hsmyif True x _ = xmyif False _ y = y

myift :: Bool -> a -> a -> amyift True x _ = xmyift False _ y = y

Page 10: PLAI Types

Dr. Philip Cannata 10

Type Judgment Trees

For the expression

{+ 2 {+ 5 7}}

For the expression

{{fun {x : number} : number

{+ x 3}}

5}

Page 11: PLAI Types

Dr. Philip Cannata 11

Type Judgment Trees(+ 3 (define add3 (lambda (x) (+ x 3))))

|- 3 : number ???

(+ 3 (define add3 (lambda (x) (+ x 3)))) : ???

We cannot construct a legal type derivation tree for the original term. However, to flag a program as erroneous, we must prove that no type derivation tree can possibly exist for that term. But perhaps some sequence of judgments that we haven’t thought of exists that (a) is legal and (b) correctly ascribes a type to the term! To avoid this we may need to employ quite a sophisticated proof technique, even human knowledge (Cycorp ?). A computer program might not be so lucky, and in fact may get stuck endlessly trying judgments!)

This is why a set of type judgments alone does not suffice: what we’re really interested in is a type system that includes an algorithm for type-checking. Sometimes a simple top-down, syntax-directed algorithm suffices (e.g., Hmm) for (a) determining the type of each expression, and (b) concluding that some expressions manifest type errors. As our type judgments get more sophisticated, we will need to develop more complex algorithms to continue producing tractable and useful type systems.

Page 12: PLAI Types

Dr. Philip Cannata 12

(letrec ((factorial (lambda (N) (if (= N 0) 1 (* N (factorial (- N 1))))))) (factorial 5))

i b v

[i <- i] |- b : [i <- i] |- v : i

|- ( letrec (i : i v ) b) :

Type Judgment - Recursion

Attempts at recursion – Text Section 26.2

{with {f {fun {i} {f i}}} {f 10}}

(let ((f (lambda (i) (f i)))) (f 10))

{with {omega {fun {x} {x x}}} {omega omega}}

(let ((omega (lambda (x) (x x)))) (omega omega))

Page 13: PLAI Types

Dr. Philip Cannata 13

(letrec ((factorial (lambda (N) (if (= N 0) 1 (* N (factorial (- N 1))))))) (factorial 5))

i b v

[i <- i] |- b : [i <- i] |- v : i

|- ( letrec (i : i v ) b) :

Type Judgment - Recursion

Maybe JDBLisp could have something like

(factorial (num) num) :: function

Page 14: PLAI Types

Dr. Philip Cannata 14

What is being Demonstrated HereWelcome to DrRacket, version 5.0.2 [3m]. Language: racket; memory limit: 128 MB.

>(+ 3 (if true 5 (define add3 (lambda (x)(+ x 3 ))))) . define: not allowed in an expression context in: (define add3 (lambda (x) (+ x 3))) > (+ 3 (if false 5 (define add3 (lambda (x)(+ x 3 ))))) . define: not allowed in an expression context in: (define add3 (lambda (x) (+ x 3)))

> (if true ((lambda (x) 'x) 5) ((lambda (x) x) 5)) 'x > (if false ((lambda (x) 'x) 5) ((lambda (x) x) 5)) 5

In Haskellmyif True x _ = xmyif False _ y = y

Main> myif True ((\ x -> 1) 5) ((\ x -> "a") 5)ERROR - Cannot infer instance*** Instance : Num [Char]*** Expression : myif True ((\x -> 1) 5) ((\x -> "a") 5)

$ cat hfac.h -- fac 0 = 1 fac n = n * fac (n-1) -- fac 0 = "a" -- fac n = n * fac (n-1)

Page 15: PLAI Types

Dr. Philip Cannata 15

s f g x = f x (g x)

k x y   = x

b f g x = f (g x)

c f g x = f x g

y f     = f (y f)

cond p f g x = if p x then f x else g x

cfac = y (b (cond ((==) 0) (k 1)) (b (s (*)) (c b pred)))

:t cfac cfac :: Integer -> Integer

cfac 5120

Type Inference – Chapter 30From my PLAI 1 Notes, page 11

( ( ( lambda (X)( (lambda (procedure)(X (lambda (arg) ((procedure procedure) arg))))( lambda (procedure)(X (lambda (arg) ((procedure procedure) arg))) ) ) )(lambda (func-arg)(lambda (n)(if (zero? n)1(* n (func-arg (- n 1)))))) ) 5)120

Main> :t s s :: (a -> b -> c) -> (a -> b) -> a -> c Main> s (\ x y -> x+y) (\ x -> x+3) 4 11

Main> :t c c :: (a -> b -> c) -> b -> a -> c Main> c (\ x y -> x+(y^2)) 4 2 18

Combinators

Page 16: PLAI Types

Dr. Philip Cannata 16

Type Inference – Chapter 30

Look at the other examples in the textbook

Page 17: PLAI Types

Dr. Philip Cannata 17

Type Inference – Chapter 30

Page 18: PLAI Types

Dr. Philip Cannata 18

Type soundness:For all programs (expressions) pe, if the type checker assigns pe the type , and if the program semantics cause pe to evaluate to a value v of type t, then the type checker will also have assigned v the type .

(first (list))

Shoud this• Return a value such as −1. • Diverge, i.e., go into an infinite loop. • Raise an exception.

Type Soundness – rewording of the first paragraph of Chapter 28

Page 19: PLAI Types

Dr. Philip Cannata 19

Type soundness:For all programs (expressions) pe, if the type checker assigns pe the type t, and if the program semantics cause pe to evaluate to a value v of type t, then the type checker will also have assigned v the type t. Otherwise one of a well-defined set of exceptions should have been raised.

Type Soundness

Page 20: PLAI Types

Dr. Philip Cannata 20

Type safety is the property that no primitive operation ever applies to values of the wrong type. By primitive operation we mean not only addition and so forth, but also procedure application. A safelanguage honors the abstraction boundaries it erects.

So what is “Strong Typing”? This appears to be a meaningless phrase, and people often use it in a nonsensical fashion. To some it seems to mean “The language has a type checker”. To others it means “The language is sound” (that is, the type checker and run-time system are related). To most, it seems to just mean, “A language like Pascal, C or Java, related in a way I can’t quite make precise”. If someone uses this phrase, be sure to ask them to define it for you. (For amusement, watch them squirm.)

Type Safety and Strongly Typed

Page 21: PLAI Types

Dr. Philip Cannata 21

statically checked not statically checkedtype safe ML, Java Schemetype unsafe C, C++ (mainly because it assembly allows embedded C)

The important thing to remember is, due to the Halting Problem, some checks simply can never be performed statically; something must always be deferred to execution time. The trade-off in type design is to maximize the number of these decisions statically without overly restricting the power of the programmer.

The designers of different languages have divergent views on the powers a programmer should have.

Type Safety

Page 22: PLAI Types

Dr. Philip Cannata 22

10

Java (Object Oriented)Java (Object Oriented)

ASPASP

RDF (Horn Clause Deduction, RDF (Horn Clause Deduction, Semantic Web)Semantic Web)

RelationRelation

Jython in JavaJython in Java

This CourseThis Course

High LevelHigh LevelLanguagesLanguages

Page 23: PLAI Types

Dr. Philip Cannata 23

Different values are usually used to solve different instances of a problem.

Would it be efficient to build the particular values into the program?

High Level Languages(Imperative or Procedural Languages)

• Traditionally the concept of a variable with a changeable association between a name and a value is used.

• Assignments are made to the variable usually multiple times.

• In other words, the same name may be associated with different values.

Relation-based Languages(Functional Languages)

• Traditionally the concept of a function application is used.

• In a function application, a function receives argument values and returns values.

• In other words, a name is only associated with one value.

Page 24: PLAI Types

Dr. Philip Cannata 24

1. Each time a scope is entered, push a new dictionary onto the stack.

2. Each time a scope is exited, pop a dictionary off the top of the stack.

3. For each name declared, generate an appropriate binding and enter the name-binding pair into the dictionary on the top of the stack.

4. Given a name reference, search the dictionary on top of the stack:

a) If found, return the binding.b) Otherwise, repeat the process on the next dictionary

down in the stack.c) If the name is not found in any dictionary, report an

error.

Symbol Table

Page 25: PLAI Types

Dr. Philip Cannata 25

Scope Concepts1. int h, i;

2. void B(int w) {3. int j, k;4. j = 2 * w * i;5. i = 2 * w;6. w = w+1;7. }8. void A (int x, int y) { 9. float i, j; 10. i = 3;11. B(h); 12. ... 13. }14. void main() {15. int a, b;16. h = 5; a = 3; b = 2;17. A(a, b);18. B(h);19. ...20. }21. void sort (float a[ ], int size) {22. int i, j;23. for (i = 0; i < size; i++) { // i, j, a, size are local24. for (j = i + 1; j < size; j++) { 25. if (a[j] < a[i]) { 26. float t; // t is local; i, j, a, size are non-local27. t = a[i];28. a[i] = a[j];29. a[j] = t;30. }31. }32. }33. }

1. Outer scope: <h, 1> <i, 1> <B, 2> <A, 8> <main, 14> <sort, 21> 1 - 33

2. Function B nested scope: <w, 2> <j, 3> <k, 3> 2 - 73. Function A nested scope: <x, 8> <y, 8> <i, 9> <j, 9> 8 - 134. Function main nested scope: <a, 15> <b, 15> 15 - 205. Function sort nested scope: <a, 21> <size, 21> <i, 22> <j, 22> 21 - 33 <t, 26> 26 - 30

Dis

join

t sco

pes n

este

d in

Out

er sc

ope

Nested scope

LifetimeSymbol Table

Dictionaries

Variables are “local” if they are in the “active” dictionary otherwise they’re non-local.

The lifetime of a variable is the time interval during which the variable has been allocated a block of memory.

Page 26: PLAI Types

Dr. Philip Cannata 26

• Assignment supports implicit widening conversions• We can transform the abstract syntax tree to insert explicit

conversions as needed.• The types of the target variable and source expression govern

what to insert.

Implicit Type Conversion

Example:Suppose we have an assignment

f = i - int(c);

(f, i, and c are float, int, and char variables).

The abstract syntax tree is:

Page 27: PLAI Types

Dr. Philip Cannata 27

Example continued:So an implicit widening is inserted to transform the tree to:

Here, c2i denotes conversion from char to int, anditof denotes conversion from int to float.

Note: c2i is an explicit conversion given by the operator int() in the program.

Implicit Type Conversion

Page 28: PLAI Types

Dr. Philip Cannata 28

Review hmm_nice_demo.zip