1 / 27

Types and Programming Languages

Types and Programming Languages. Lecture 10. Simon Gay Department of Computing Science University of Glasgow. 2006/07. Recursion with References. A recursive function definition:. f = x. if x==0 then 1 else x*f(x-1). can be expressed without explicit recursion:.

selinaj
Télécharger la présentation

Types and Programming Languages

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Types and Programming Languages Lecture 10 Simon Gay Department of Computing Science University of Glasgow 2006/07

  2. Recursion with References A recursive function definition: f = x.if x==0 then 1 else x*f(x-1) can be expressed without explicit recursion: f = let val g = ref (x:int.x) in g := x:int. if x==0 then 1 else x * (!g)(x-1)); !g end Exercise: check that f(2) behaves correctly. Types and Programming Languages Lecture 10 - Simon Gay

  3. Subtyping Imagine BFL with types int and float. If we have f : float  float and v : int then of course we cannot typecheck f(v). But this seems too strict: mathematically we think of the set of integers as a subset of the set of floating point numbers, so we would like to be able to regard v as a float and apply f to it. (At some level of abstraction we want to say that an int is also a float, but note that computation is required to convert the representation of an integer into the representation of the corresponding floating point number, and it might not be possible to do this accurately.) Types and Programming Languages Lecture 10 - Simon Gay

  4. Subtyping We can formalize this idea by introducing subtyping. Type T is a subtype of type U, written T <: U, if a value of type T can safely be used anywhere that a value of type U is expected. Conversely we say that U is a supertype of T. It is usually possible to understand T <: U as “every value described by T is also described by U” or “the set of values of T is a subset of the set of values of U”. The crucial rule which brings subtyping into the type system is the rule of subsumption: (T-Sub) Types and Programming Languages Lecture 10 - Simon Gay

  5. Defining the subtype relation The subtype relation is defined by a collection of inference rules. General rules: subtyping should be reflexive and transitive. (S-Trans) (S-Refl) Rules for base types are a language design choice. It is common to include natural relationships among numeric types: int <: float float <: double but relationships such as bool <: int or char <: int are probably undesirable. Types and Programming Languages Lecture 10 - Simon Gay

  6. Subtyping record types When should a record type be a subtype of another record type? Example: r:{x:int}. #x(r) has type {x:int}  int Giving this function an argument of type {x:int, y:int} should be allowed. For example, (r:{x:int}. #x(r)){x=1,y=2} * 1 without any run-time errors. In fact, any record which includes a field x:int is acceptable. In general: (S-RcdWidth) This is called the width subtyping rule for record types. Types and Programming Languages Lecture 10 - Simon Gay

  7. Subtyping record types So: one way to create a subtype of a record type is to add more fields. Think: a record type {x:int} describes the set of records with at least a field x of type int. It is also safe to vary the types of individual fields, as long as this variation respects the subtype relation. Example: if sqrt : float  float and f = r:{x:float}. sqrt(#x(r)) then f : {x:float}  float . It is safe to apply f to an expression of type {x:int} because int <: float . So: {x:int} <: {x:float} Types and Programming Languages Lecture 10 - Simon Gay

  8. Subtyping record types This gives us the depth subtyping rule for record types: (S-RcdDepth) Examples combining width and depth subtyping. Types and Programming Languages Lecture 10 - Simon Gay

  9. Subtyping record types Even if we decided that the order of the fields is significant, we can use subtyping to relax this requirement. (S-RcdPerm) Examples of combinations of the subtyping rules for records. Types and Programming Languages Lecture 10 - Simon Gay

  10. Subtyping function types In a language in which functions are values, we must define a subtyping rule for function types. Example: f = x:intfloat. sqrt(x(2)) so f : (intfloat)float which types of function can safely be given to f ? If g : intfloat then of course f(g) is safe. If g : intint then is f(g) safe? If g : floatint then is f(g) safe? If g : floatfloat then is f(g) safe? Types and Programming Languages Lecture 10 - Simon Gay

  11. Subtyping function types The rule for subtyping function types is (S-Arrow) The direction of the subtype relation is reversed (contravariant) for the argument types in the left-hand hypothesis, but it is the same (covariant) for the result types as for the function types. It is not safe to say that intint <: floatfloat Example: f = x:floatfloat. sqrt(x(2.3)) so f : (floatfloat)float If g : intint then f(g) evaluates g(2.3) which is an error. Types and Programming Languages Lecture 10 - Simon Gay

  12. The Top Type It is convenient to have a type that is a supertype of every type. This type is called Top (think of it as a new base type) and the subtyping rule is T <: Top (S-Top) Any typable expression can be considered to have type Top. Top is similar to the type Object in Java, except that in Java, Object is only a supertype of every object type; for example int is not a subtype of Object. Types and Programming Languages Lecture 10 - Simon Gay

  13. Objects Following Pierce (Chapter 18) we will look at how the language features we have been studying can be used to construct objects with behaviour familiar from OO languages. What is an object? A data structure encapsulating some internal state and providing a collection of methods which allow access to this state. Example: a counter object, holding an integer value and providing get and inc methods. Types and Programming Languages Lecture 10 - Simon Gay

  14. A Counter Object Let’s give the name c to an expression representing a counter. c = let val x = ref 1 in { get =  _:unit . !x, inc =  _:unit . x := (!x)+1 } end The type of c is { get: unit -> int, inc: unit -> unit } The scoping rules mean that x is private, but can be used by both get and inc. Types and Programming Languages Lecture 10 - Simon Gay

  15. Using the counter To call a method we extract a field of the record and apply it. returns () c.inc() c.get() returns 2 (Change notation: write c.inc instead of #inc(c)) What we are really doing: let val c = let val x = ref 1 in { ... } end in c.inc(); c.get() end Types and Programming Languages Lecture 10 - Simon Gay

  16. Using the counter We can define an abbreviation for the type of the counter: Counter = { get: unit -> int, inc: unit -> unit } A function which uses a counter object: inc3 = x:Counter.(x.inc(); x.inc(); x.inc()) Example: Reduction sequences for expressions involving counters. Types and Programming Languages Lecture 10 - Simon Gay

  17. Subtyping object types Extending the object type by adding a new method: Counter = { get: unit -> int, inc: unit -> unit } ResetCounter = { get: unit -> int, inc: unit -> unit, reset: unit -> unit } According to the subtyping rules, ResetCounter <: Counter. This is what we would expect in an OO language (e.g. Java) if we define class ResetCounter extends Counter . Types and Programming Languages Lecture 10 - Simon Gay

  18. Method overriding When a subclass is defined in Java, it is possible for a method to be overridden by a method of the same name and type. class Counter { float x; float get() { return x; } void inc() { x = x + 1; } } class NewCounter extends Counter { float get() { return x+1; } } This does not change the corresponding record type: { get: unit -> float, inc: unit -> unit } Types and Programming Languages Lecture 10 - Simon Gay

  19. Method overriding Using the flexibility of record subtyping, it would be safe to allow variation of method types when overriding, e.g.: class IntCounter extends Counter { int y; int get() { return y; } void inc() { y = y + 1; } } The type of IntCounter as a record is { get: unit -> int, inc: unit -> unit } which is a subtype of { get: unit -> float, inc: unit -> unit } Contravariant modification of method parameter types is also safe. Types and Programming Languages Lecture 10 - Simon Gay

  20. References and subtyping The Ref type constructor must be invariant to preserve safety. (S-Ref) For Ref S to be a subtype of Ref T, S and T must each be a subtype of the other – they must be equivalent in the subtype relation. This means that either S and T are identical, or they are record types with the same fields in a different order. Why is such a severe restriction necessary? Types and Programming Languages Lecture 10 - Simon Gay

  21. References and subtyping A value of type Ref T can be used in two different ways in a given context: for reading (!) or for writing (:=). When used for reading, the context expects to obtain a value of type T, so if the reference actually holds a value of type S then we must have S <: T. If the reference is used for writing then the context will write a value of type T. If the actual type of the reference is Ref S, then at some other point the value will be used as if it had type S; this is only safe if T <: S. Types and Programming Languages Lecture 10 - Simon Gay

  22. Arrays and subtyping An array is a collection of references of the same type, so the subtyping rule is invariant in the same way as the rule for references. (S-Array) Java permits covariant subtyping of arrays: (S-ArrayJava) This is unsafe and requires every array assignment to have a run-time type check! Types and Programming Languages Lecture 10 - Simon Gay

  23. Unsafe array subtyping in Java Why does Java provide this unsafe subtyping rule for arrays? To allow flexibility of programming in situations such as void reverse(Object[] a) so that an array of any type can be given to reverse as a parameter. Int[] a = new Int[100]; ... reverse(a); But this comes at a very high cost, and better solutions are possible through parametric polymorphism (as we will see later). Types and Programming Languages Lecture 10 - Simon Gay

  24. Arrays and Subtyping in Java void f(Object[] x) { x[0] = new Object(); } String[] a = new String[10]; for (int i = 0; i < 10; i++) a[i] = “Test”; f(a); System.out.println (a[0].concat(“A”)); Types and Programming Languages Lecture 10 - Simon Gay

  25. Casts Java (and other languages) provide casting which forces a value of one type to be regarded as having another type. Upcasts: if S <: T and e:S then writing (T)e is harmless and just has the effect of losing information about e . Example: if we have c:ResetCounter and we write d = (Counter)c then referring to d does not allow us to use the reset method. Downcasts: if S <: T and e:T then writing (S)e requires a run-time check that e actually does have type S. For example, e might be the result of upcasting a value of type S. Types and Programming Languages Lecture 10 - Simon Gay

  26. Downcasting A very common use of downcasting is when using generic data structures. Example (in Java before 1.5): if we want to use a Hashtable then usually we are storing a specific type of object, but all the methods of the Hashtable class have types involving Object in order to make them generic. Hashtable h = new Hashtable(); MyClass m = new MyClass(...); h.put(“Simon”,m); ... MyClass n = (MyClass)h.get(“Simon”); because Object get(Object key) in Hashtable. Again, the right solution is parametric polymorphism (see later). Types and Programming Languages Lecture 10 - Simon Gay

  27. Reading Pierce: 15.1, 15.2, 15.3, 15.4, 15.5, 18.1-18.7. Exercises Pierce: 15.2.1, 15.2.5, 15.5.2, 15.5.3. Types and Programming Languages Lecture 10 - Simon Gay

More Related