Type System, Type Judgments, Type Rules - Slide Notes | CMSC 631, Study notes of Computer Science

Material Type: Notes; Professor: Hicks; Class: PROG ANLYS&UNDERSTANDING; Subject: Computer Science; University: University of Maryland; Term: Unknown 1989;

Typology: Study notes

Pre 2010

Uploaded on 02/13/2009

koofers-user-pzg
koofers-user-pzg 🇺🇸

10 documents

1 / 38

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Type Systems
CMSC 631 – Program Analysis and
Understanding
Fall 2007
2
CMSC 631
Not all programs accepted by a language’s
grammar are actually defined (e.g., they do not
have a normal form):
(1 (λx. λy. x y))
The (app) rule expects a function as the first argument,
but statement expects a list, but here it has been given
a numeral. There is no rule to evaluate such a
program, so we’re “stuck.”
It would be great to rule out such non-sensical
programs in advance, so we can a program can
never reach a “stuck state.”
The Need for a Type System
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26

Partial preview of the text

Download Type System, Type Judgments, Type Rules - Slide Notes | CMSC 631 and more Study notes Computer Science in PDF only on Docsity!

Type Systems CMSC 631 – Program Analysis and Understanding Fall 2007 CMSC 631 2

  • Not all programs accepted by a language’s

grammar are actually defined (e.g., they do not

have a normal form):

■ (1 (λx. λy. x y)) ■ The (app) rule expects a function as the first argument, but statement expects a list, but here it has been given a numeral. There is no rule to evaluate such a program, so we’re “stuck.”

  • It would be great to rule out such non-sensical

programs in advance, so we can a program can

never reach a “stuck state.”

The Need for a Type System

CMSC 631 3

  • A type system is some mechanism for distinguishing

good programs from bad

■ Good programs = well typed ■ Bad programs = ill typed or not typable

  • Examples: ■ 0 + 1 // well typed ■ false 0 // ill-typed: can’t apply a boolean ■ 1 + (if true then 0 else false) // ill-typed: can’t add boolean to integer What is a Type System? CMSC 631 4
  • “A type system is a tractable syntactic method

for proving the absence of certain program

behaviors by classifying phrases according to the

kinds of values they compute.”

■– Benjamin Pierce, Types and Programming Languages A Definition of Type Systems

CMSC 631 7

  • A type environment (a.k.a. context ) is a map from

variables to types (a kind of symbol table)

is the empty type environment

  • A closed term e is well-typed if ⊢ e : t for some t
  • We’ll abbreviate this as ⊢ e : t ■ A, x:t is just like A, except x now has type t
  • The type of x in A, x:t is t
  • The type of z≠x in A, x:t in the type of z in A
  • When we see a variable in a program, we look in the

type environment to find its type

■ All of this is similar to the store s we’ve been using for the language of commands, but here is applied to typing Type Environments CMSC 631 8 Type Rules A ⊢ n : int x dom(A) A ⊢ x : A(x) A, x:t ⊢ e : t′ A ⊢ λx:t.e : t→t′ A ⊢ e1 : t→t′ A ⊢ e2 : t A ⊢ e1 e2 : t′

CMSC 631 9 Example

  • dom(A) A ⊢ - : int→int A ⊢ 3 : int A ⊢ - 3 : int A = - : int→int CMSC 631 10 Another Example
  • dom(B) x dom(B) B ⊢ 3 : int A ⊢ 4 : int B ⊢ + : i→i→i B ⊢ x : i B ⊢ + x : int→int B ⊢ + x 3 : int A ⊢ (λx:int.+ x 3) : int→int A ⊢ (λx:int.+ x 3) 4 : int A = + : int→int→int B = A, x : int We’d usually use infix x + 3

CMSC 631 13 Progress

  • Suppose ⊢ e : t. Then either e is a value, or there

exists e’ such that e → e′

  • Proof by induction on e ■ Base cases n, λx:t.e – these are values, so we’re done ■ Base case x – can’t happen (empty type environment) ■ Inductive case e1 e2 – If e1 is not a value, then by induction we can evaluate it, so we’re done, and similarly for e2. Otherwise both e1 and e2 are values. Inspection of the type rules shows that e1 must have a function type, and therefore must be a lambda since it’s a value. Therefore we can make progress. CMSC 631 14 Preservation
  • If A ⊢ e : t and e → e′ then A ⊢ e′ : t
  • Proof by induction on e ■ Base cases n, x, λx:t.e – Impossible, since these terms don’t reduce
  • But: what if we were using the nondeterministic semantics? ■ Induction. Assume A ⊢ e1 e2 : t and e1 e2 → e′. Then we have A ⊢ e1 : t′ → t and A ⊢ e2 : t′. (Why?) ■ Then there are three cases.
  • If e1 → e1′ then by induction A ⊢ e1’ : t′ → t, so e1′ e2 has type t by the typing rule for applications
  • If reduction inside e2, similar

CMSC 631 15 Preservation, cont’d

  • Otherwise (λx.e) v → e[v\x]. Then we have ■ Thus we have - A, x : t′ ⊢ e : t - A ⊢ v : t′ ■ Then by the substitution lemma (next slide) we have - A ⊢ e[v\x] : t ■ And so we have preservation A, x: t′ ⊢ e : t A ⊢ λx.e : t′→t CMSC 631 16 Substitution Lemma
  • If A ⊢ v : t and A, x:t ⊢ e : t′, then A ⊢ e[v\x] : t′
  • Proof: Induction on the structure of e
  • For the lazy semantics, we’d have to prove

something stronger

■ If A ⊢ e1 : t and A, x:t ⊢ e : t′, then A ⊢ e[e1\x] : t′

CMSC 631 19

  • e ::= ... | inL t

e | inR

t

e

  • | (case e of x1:t1 → e1| x2:t2 → e2) Sum Types (Tagged Unions) A ⊢ e : t A ⊢ inL t e : t1 + t A ⊢ e : t A ⊢ inR t e : t1 + t A ⊢ e : t1 + t A, x1:t1 ⊢ e1 : t A, x2:t2 ⊢ e2 : t A ⊢ (case e of x1:t1 → e1 | x2:t2 → e2) : t CMSC 631 20
  • Self application is not checkable in our system ■ It would require a type t such that t = t→t′
  • (We’ll see this next, but so far...)
  • The simply-typed lambda calculus is strongly

normalizing

■ Every program has a normal form ■ I.e., every program halts! Self Application and Types A, x:? ⊢ x : t→t′ A, x:?^ ⊢^ x : t A, x:? ⊢ x x : ... A ⊢ λx:?.x x : ...

CMSC 631 21

  • We can type self application if we have a type to

represent the solution to equations like t = t→t′

■ We define the type μα.t to be the solution to the (recursive) equation α = t ■ Example: μα.int→α Recursive Types or CMSC 631 22

  • We can check type equivalence with the previous

definition

■ Standard unification, omit occurs checks

  • Alternative solution: ■ The programmer puts in explicit fold and unfold operations to expand/contract one “level” of the type trees - unfold μα.t = t[μα.t\α] - fold t[μα.t\α] = μα.t Folding and Unfolding unfold fold

CMSC 631 25 ML Datatypes Example

  • type list = Int of int | Cons of int * int list ■ Equivalent to μα.int+(int × α)
  • (Int 3) equivalent to ■ fold (inLint×μβ.int+(int×β) 3)
  • (Cons (2,(Int 3)) equivalent to ■ fold (inRint (2, fold (inLint×μβ.int+(int×β) 3)))
  • match e with Int x -> e1 | Cons x -> e2 same as ■ case (unfold e) - x:int → e - | x: int×(μβ.int+(int×β)) → e CMSC 631 26
  • In the pure lambda calculus, every term is typable

with recursive types

■ (Pure = variables, functions, applications only)

  • Most languages have some kind of “recursive” type ■ E.g., for data structures like lists, tree, etc.
  • However, usually two recursive types that define

the same structure but use a different name are

considered different

■ E.g., struct foo { int x; struct foo *next; } is different from struct bar { int x; struct bar *next; } Discussion

CMSC 631 27

  • We’ve discussed simple types so far ■ Integers, functions, pairs, unions ■ Extensions for recursive types
  • Type systems have nice properties ■ Type checking is straightforward (may need annotations) ■ Well typed programs don’t go “wrong” - They don’t get stuck in the operational semantics
  • But...We can’t type check all good (untyped) lambda

calculus programs

■ Can you come up with an example? Recap CMSC 631 28

  • How can we build more flexible type systems? ■ More programs type check ■ Type checking is still tractable
  • How can reduce the annotation burden? ■ Type inference Up Next: Improving Types

CMSC 631 31

• Polymorphic functions map types to terms

■Normal functions map terms to terms

• Examples

■Λα.λx:α.x : α.α→α

■Λα.Λβ.λx:α.λy:β.x : α. β.α→β→α

■Λα.Λβ.λx:α.λy:β.y : α. β.α→β→β

Defining Polymorphic Functions

CMSC 631 32

• When we use a parametric polymorphic type, we

apply (or instantiate) it with a particular type

■ In System F this is done by hand: ■ (Λα.λx:α.x)[t1] : t1 → t ■ (Λα.λx:α.x)[t2] : t2 → t

• This is where the term parametric comes from

■ The type α.α→α is a “function” in the domain of types, and it is passed a parameter at instantiation time

Instantiation

CMSC 631 33

  • Notice that there are no constructs for

manipulating values of polymorphic type

■ This justifies instantiation with any type - that’s what the forall means!

  • Note also that we are adding α to A; we could

(should?) use this to ensure types are well-

formed

Type Rules A ⊢ e : α.t A ⊢ e[t′] : t[t′\α] A,α ⊢ e : t A ⊢ Λα.e : α.t CMSC 631 34

  • We have to extend substitution to include types;

that’s up next …!

Small-step Semantics Rules

e → e’

(Λα.e)[t] → e[t\α] e[t] → e’[t]

(type-app) (^) (tapp-cong)

CMSC 631 37

  • Let’s consider the simply typed lambda calculus

with integers

■ e ::= n | x | λx.e | e e ■ (No parametric polymorphism)

  • Type inference : Given a bare term (with no type

annotations), can we reconstruct a valid typing

for it, or show that it has no valid typing?

■ Notice that lambda terms above have no type annotation Type Inference CMSC 631 38

  • Problem: Consider the rule for functions
  • Without type annotations, where do we get t? ■ We’ll use type variables for as-yet-unknown types - t ::= α | int | t → t ■ We’ll generate equality constraints t = t among the types and type variables - And then we’ll solve the constraints to compute a typing Type Language A, x:t ⊢ e : t′ A ⊢ λx:t.e : t→t′

CMSC 631 39 Type Inference Rules A ⊢ n : int x dom(A) A ⊢ x : A(x) A, x:α ⊢ e : t′ α fresh A ⊢ λx.e : α→t′ A ⊢ e1 : t 1 A ⊢ e2 : t t1 = t2 →β β fresh A ⊢ e1 e2 : β

“Generated” constraint

CMSC 631 40

  • We collect all constraints appearing in the derivation

into some set C to be solved

  • Here, C consists of one constraint α→α = int →β ■ Solution: α = int = β
  • Thus this program is typable, and we can derive a

typing by replacing α and β by int in the proof tree

Example A, x:α ⊢ x:α A ⊢ (λx.x) : α→α A ⊢ 3 : int α→α = int →β A ⊢ (λx.x) 3 : β