Polymorphic Type Inference for Languages with Overloading and Subtyping Geoffrey Seward Smith Fh.D Thesis 91-1230 August 1991 Department of Computer Science Cornell University Ithaca, NY 14853-7501 POLYMORPHIC TYPE INFERENCE FOR LANGUAGES WITll OVERLOADING AND SUBTYPING A Dissertation Presented to the Faculty of the Graduate School of Cornell University in Partial Fulfillment of the Requirements for the Degree of Doctor of Philosophy by Geoffrey Seward Smith August 1991 Oc Geoffrey Seward Smith 1991 ALL RIGHTS RESERVED POLYMORPHIC TYPE INFERENCE FOR LANGUAGES WITH OVERLOADING AND SUBTYPING Geoffrey Seward Smith, Ph.D. Cornell University 1991 Many computer programs have the property that they work correctly on a variety 0 types of input; such programs are called polymorphic. Polymorphic type systems support polymorphism by allowing programs to be given multiple types. In this way, programs are permitted greater flexibility of use, while still receiving the benefits of strong typing. One especially successful polymorphic type system is the system of Hindley, Milner, and Damas, which is used in the programming language ML. This type system allows programs to be given universally quantified types as a means of expressing polymorphism. It has two especially nice properties. First, every well-typed program has a "best" type, called the principal type, that captures all the possible types of the program. Second, principal types can be inferred, allowing programs to be written without type declarations. However, two useful kinds of polymorphism cannot be expressed in this type system: overloading and subtyping. Overloading is the kind of polymorphism exhibited by a function like addition, whose types cannot be captured by a single universally quantified type formula. Subtyping is the property that one type is contained in another, as, for example int C real. This dissertation extends the Hindley/Milner/Damas type system to incorpo- rate overloading and subtyping. The key device needed is constrained universal quantification, in which quantified variables are allowed only those instantiations that satisfy a set of constraints. We present an inference algorithm and prove that it is sound and complete; hence it infers principal types. An issue that arises with constrained quantification is the satisfiabitity of constraint sets. We prove that it is undecidable whether a given constraint set is satisfiable; this difficulty leads us to impose restrictions on overloading. An interesting feature of type inference with subtyping is the necessity of sim- plifying the inferred types the unsimplified types are unintelligible. The sim- plification process involves shape unification, graph algorithms such as strongly connected components and transitive reduction, and simplifications ba??d on the monotonicities of type formulas. Biographical Sketch Geoffrey Seward Smith was born on December 30, 1960 in Carmel, California. His childhood was spent in Bethesda, Maryland. In 1982, he graduated, summa cnm taude, from Brandeis University with the degree of Bachelor of Arts in Math- ematics and Computer Science. In 1986, he received a Master of Science degree in Computer Science from Cornell University. He was married to Maria Elena Gonzalez in 1982, and in 1988 he and his wife were blessed with a son, Daniel. iii To Elena and Daniel lv Acknowledgements My advisor, David Gries, has been a patient, encouraging teacher. His high standards and devotion to the field have been an inspiration to me. His warmth and humanity have made it a pleasure to work with him. Thanks also to my other committee members, Dexter Kozen and Stephen Chase. I have always marveled at Dexter's depth and breadth of knowledge; he has taught me a great deal throughout my years at Cornell. Cornell has been a wonderful place to learn and grow; I am indebted to many people here who have taught and inspired me. Dennis Volpano discussed much of the material in this dissertation with me, and his comments and suggestions helped to shape this work. Bard Bloom gave me valuable insight into the shape unification problem. Discussions with Hal Perkins, Earlin Lutz, Steve Jackson, Naixao Zhang, and the other members of the Polya project have added greatly to my understanding of programming languages and type systems. I have had a very nice group of officemates during my time at Cornell. For friendship, advice, and encouragement, I thank Amy Briggs, Jim Kadin, Daniela Rus, and Judith Underwood. Finally, I thank Elena and Daniel for their love and support across the years. v Table of Contents 2 3 Introduction 1.1 Types 1.2 Reductionist Type Correctness . . . . 1.3 Polymorphism 1.4 Axiomatic Type Correctuess . . . . 1.5 The Hindley/Milner/Damas Type System 1.6 Extensions to Hindley/Milner/Damas Polymorphism. Overloading 2.1 The Type System . . . . . . . . . . . 2.1.1 Types and Type Schemes 2.1.2 Substitution and o -equivalence . . . 2.1.3 The Typing Rules 2.1.4 The Instance Relation and Principal Types . . 2.2 Properties of the Type System 2.3 Algorithm Wo. . . . . 2.4 Properties of W0 . . . . . . 2.4.1 Soundness of W0 . . . . . . . . 2.4.2 Completeness of W0 . . . 2.5 Limitative Results. . . . . . 2.5.1 A Logical Digression 2.6 Restricted Forms of Overloading . . . . 2.7 Conclusion Subtyping 3.1 The Type System 3.1.1 Types and Type Schemes 3.1.2 Substitution and a -equivalence 3.1.3 The Typing Rules 3.1.4 The Instance Relation 3.2 Properties of the Type System 3.3 Algorithm W08 . . . vi 2 3 6 8 10 13 13 14 14 17 22 24 30 35 35 38 52 57 57 60 61 61 62 62 62 64 65 69 3.4 3.5 3.6 3.7 3.8 Properties of W08 3.4.1 Soundness of W08 . . . . . . 3.4.2 Completeness of W08 An Example Assumption Set . Type Simplification 3.6.1 An Overview of Type Simplification 3.6.2 Transformation to Atomic Inclusions 3.6.3 Collapsing Strongly Connected Components 3.6.4 Monotonicity-based Instantiations 3.6.5 Function close . . . . . . Satisfiability Checking . . Conclusion . . . . . . . . . Conclusion 4.1 A Practical Look at Type Inference 4.2 Related Work . . 4.3 Future Directions . . . . . . . 4.3.1 Satisfiability of Constraint Sets 4.3.2 Records . . . . . . . 4.3.3 Semantic Issues . . . 4.3.4 Imperative Languages . . 4 A Omitted Proofs Bibliography vii 69 69 71 84 86 86 91 94 96 100 102 105 106 106 109 110 110 111 111 111 112 120 List of Figures 2.1 2.2 2.3 2.4 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 4.1 4.2 4.3 4.4 Typing Rules with Overloading Algorithm W0 Function close . . Example lexicographic Additional Rules for Subtyping . . . . Algorithm Wos . Assumption Set A0. . . Atomic Inclusions for lexicographic Collapsed Components of lexicographic . . . . ResultofShrinking c, v, A, ?, ?, ?,and 0 Function shape-unifier . . . . . . . . . Function atomic-inclusions Function component-collapser . . . . Function close . . . . . . Example fast-expon Example mergesort Example reduce-right . Example another-reduce-right viii 18 31 33 34 63 70 85 88 89 90 92 93 95 101 107 108 109 109 Chapter 1 Introduction Over the years, the notion of types in programming languages has grown steadily in importance and depth. In recent years, the study of types has been enriched by the introduction of ideas from mathematical logic. Yet, many basic questions about types remaan unresolved there is still no consensus about what exactly types are, or about what it means for a computer program to be type correct. What follows in this chapter, then, is an attempt to outline what is most impor- tant about types and type systems. 1.1 Types It seems fundamental to human intelligence to class?fy the objects of the world based on their observed similarities and differences. This process of classifica- tion is a basic way of dealing with the complexity of the world: by grouping together similar objects, we may abstract away from particular objects and study properties of the group as a whole. In the realm of mathematics, the process of grouping together similar objects has led to the identification of a rich diversity of mathematical structures, for example Euclidean spaces, topological spaces, and categories. The study of a mathematical structure leads to the development of a theory of the structure; the theory describes the common properties of the members of the structure and facilitates reasoning about the structure. Reasoning about a structure is further facilitated by the establishment of specialized notation tailored to the structure. Many mathematical structures are also useful computational structures; for example graphs, sets, and sequences are especially useful in programming. In computer science, we call such structures types. A type, then, is a set of elements and operations having an associated theory that allows reasoning about manipulations of elements of the type. The programming process is much easier in a language with a rich collection of types; this is perhaps the most important feature of high-level languages. Hence 2 a major consideration in the design of any such language is how types will be supported. Type support may be divided into two relatively independent aspects: first, to ensure that high-level types are correctly implemented in terms of the low-level data structures available on an actual machine, and second, to ensure that programs use types only in ways that are sensible. The first of these we call reductionist type correctness, the second we call axiomatic type correctness. We explore these in more detail in the next three sections. 1.2 Reductionist Type Correctness Since actual machines have but a few types (for example, integers of various sizes, floating-point numbers, arrays, and pointers), a major task of a compiler is to implement the types of a high-level language in terms of low-level data structures. The implementation of types is complicated by the fact that many types (for example, sets) have no best implementation that is appropriate for all situations. Instead, different implementations should be used depending on the kind and frequency of the operations to be performed. As a rule, programming languages have not attempted to use multiple im- plementations for built-in types 1; instead, the usual approach is to provide a language facility that allows the programmer to define a new type and to give its representation in terms of other types. The key issue is how to protect the representation from misuse. Suppose that we wish to implement a type dictionary with operations insert and member?. We might chose to represent the dictionary as a bit-vector. But this should not mean that type dictionary is the same as type bit-vector! For, outside the procedures insert and member?, there should be no access to the underlying representation. Furthermore, just because a value has type bit-vector we cannot conclude that the value represents a dictionary. The two concerns are called "secrecy" and "authentication" by Morris [Mor73], and they lead him to declare that "types are not sets". This appears to contradict our definition of type above, but this is really not the case. Morris is discussing what is needed for one type to represent another; he is not discussing the nature of types. In general, it can be argued that a failure to distinguish between reductionist and axiomatic type correctness has led to a great deal of confusion about the nature of types. Cardelli and Wegner follow in the reductionist style when they state, A type may be viewed as a set of clothes (or a suit of armor) that protects an underlying untyped representation from arbitrary or un- intended use. [CW85, p. 474] 1 SE?TL is an exception. 3 Similarly, in the language Russell [DD85], the notion of strong typing is defined so that the meaning of a well-typed program is independent of the representations of the types it uses. In a similar way, Mitchell and Plotkin [MP88J suggest that an abstract type that is represented by another type should be given an existentially quantified type as a way of hiding the representation. Aho, Hopcroft, and Ullman [AHU83] assert that two types should be regarded as different if the set of operations they support is different, because the set of operations to be supported is crucial in determining the best implementation of a type. From the point of view of the programmer, however, this view of types seems inappropriate: it is a case of reductionist concerns contaminating the axiomatic view of types. A better way of understanding the situation is in terms of partial implementations of the same type [GP85,Pri87,GV89]. In the rest of this dissertation, we will not consider reductionist type cor- rectness further. Instead we will think of types as existing axiomatically, and we will not worry about how they are represented. Henceforth, then, we will focus on axiomatic type correctness. Before we do so, we consider the notion of polymorphism. 1.3 Polymorphism In mathematics, the study of a proof of a theorem may reveal that the theorem can be generalized. For example, in analyzing a proof of a theorem about the natural numbers, we might realize that the only property of the natural numbers needed is that they form a well-ordered set. This realization would enable us to generalize our theorem to any well-ordered set. Lakatos gives a fascinating account of the role of proof analysis in mathematical discovery in [Lak76]. To exploit this useful principle of generalization, we rewrite our theorems so that they refer to abstract mathematical structures (e.g. well-ordered sets, topological spaces) that have certain properties but whose identity is not fixed. Poincare' describes the process thus: ... mathematics is the art of giving the same name to different things ... When the language is well-chosen, we are astonished to learn that all the proofs made for a certain object apply immediately to many new objects; there is nothing to change, not even the words, since the names have become the same. [Poil3, p. 375] Indeed, a great trend in twentieth-century mathematics has been the rise of abstract mathematical structures; rather than studying the properties of par- ticular mathematical structures (for example Euclidean space), mathematicians today are more likely to study properties of abstract mathematical structures (for example metric spaces). Abstract mathematical structures are essentially proof 4 generated; that is, they are defined by abstracting out those properties needed for certain proofs to be carried through. In computer science, similarly, the study of a correctness proof of an algorithm may reveal that the algorithm works for many types of objects. Suppose for example that exponentiation is defined by x0 =1 and x?+1 = (?)* x. Consider the following algorithm, which uses only O(log n) multiplications: expon(x,n) = if n = 0 then 1 else if even?(n) then expon(x * x, n + 2) else expon(x,n --H 1) * x In proving the correctness of expon, we require that n be a nonnegative integer, but we do not need to fix the type of x. All that is needed is for the type of x to have an associative operation * with multiplicative identity 1. Hence, expon should be applicable to many types of inputs. The principle of generalization goes by the name of polymorphism in computer science, except that it is common to encumber the concept of polymorphism with irrelevant implementation cun?ideratit,ii?; iii p?rticular, it i? iiormally demanded that a polymorphic function execute the same machine code, regardless of the types of its inputs. 2 Following Poincare', we can say that the basis for polymorphism is the use of the same name for different objects, which allows programs that use these names to apply to many types of inputs. For example, we allow the identifiers cons and * to refer to many different functions, depending on the argument types. More precisely, we say that cons and * have many types and that they have a meaning corresponding to each of their types: cons : Vo.a H seq(o) H seq(a) describes the types of cons, ? and * : int H int H int * : real `. real H real * : complex H complex H complex gives some of the types of *. 2 The discussion of Cardelli and Wegner [CW85] is typical; Prins [Pri87], in contrast, argues against the necessity of uniform implementations for polymorphic functions. ? Throughout this dissertation, we use curryin9 to avoid the messiness of functions with mul- tiple arguments. 5 Notice that the types of consare all described by a single universally quantified type formula; we therefore say that cons is parametrically polymorphic. The types of *, in contrast, cannot be uniformly described: they require many type formulas. For this reason, * is said to be overloaded. With respect to the generalization principle, which seems to be the true foundation of polymorphism, there is no essential difference between paramet- ric polymorphism and overloading. Traditionally, however, overloading has been regarded as less genuine and significant than parametric polymorphism; indeed overloading is often belittled as ad-hoc polymorphism.4 This disdain for over- loading seems to stem mostly from the desire for uniform implementations it is easy to give an implementation of C0flS that works for all kinds of sequences, but * requires different machine code for integers than for floating-point numbers. In fact the usual way of treating the overloaded operators in a program is to demand that the local context determine a particnlar overloading to be used at each point; see, for example, [ASU86]. This is even the case in the polymorphic language ML [WB89J. But this treatment of overloading destroys the polymor- phism of expon above: choosing a particular overloading of * to be used by expon arbitrarily restricts expon to a single argument type. Another common assertion is that overloaded identifiers have only finitely many types, in contrast to parametrically overloaded identifiers, which have in- finitely many types. This need not be so, however. Consider the operation <. Two of its types are real real bool and char char H bool. In addition, < may be used to compare sequences lexicographically (that is, by dictionary order). What sequences can be compared in this way? Precisely those sequences whose elements can be compared witii ?A. Definition 2.1 (Va with C. r) >A r' if there is a s?bstitution [a? := 7r] such that o+ AHC[a:=r] and o+ r[c := = Furthermore we say that a >A a' if for all r, a' >A T implies a >A T. In this case we say that a is an instance of a with respect to A. This definition has the property that if a >A T, then for any e, A H e : a implies A H e : r, because the derivation of A H e : a can be extended using (V-elim). Like the >A relation of Wadler and Blott [WB89], our >?A relation general- izes the > relation of Damas and Milner [DM82]. Unlike Wadler and Blott, however, we follow the approach of Mitchell and Harper [MH88] in defining a >?A a' .3 It is easy to see that >A is reflexive and transitive and that a >?A r is well defined. In a polymorphic type system, an expression e may have many typings, and it is therefore desirable to have some "best" typing, which in some way subsumes all other typings. The notion of a principal typing makes this precise. Definition 2.2 The typing A ? e : a is said to be principal if for all typings A H e a', a >A a'. In this case a is said to be a principal type for e with respect to A Principal types in our system cannot be understood by themselves; they de- pend upon the assumption set A. If we say that the principal type with respect to A of the exponentiation function expon is Va with * : a a a, 1 : a. a . int a we must look at A to discover what overloadings of * and 1 are available. Only then do we know how expon can be used. 3The Damas/Milner approach to defining ff > j' is syntactic; roughly speaking, it says that ?`ifa derivation of A He: ? can be extended to a derivation of A He: a' using (Velim) followed by (V-intro). The Mitchell/Harper approach, in contrast, is semantic. On > the two approaches are equivalent, but on >A the syntactic approach (adopted by Wadler and Blott) is weaker. 23 Because one must look to the assumption set A to determine what overload- ings are available, overloaded symbols do not have very satisfying principal types. For example, suppose that A contains the following assumptions: : char H char H boot, : real H real boot, _ : V? with ? : a 0 H boot. seq(a) H seq(a) H boot Then one principal type for < with respect to A is Va with <: 0.0, which obviously doesn't convey anything! A somewhat better principal type is Va with <: a a boot. a a H boot but this isn't very informative either. 4 In practice, of course, one is seldom interested in the principal types of overloaded symbols; it is the principal types of compound programs, like expon, that are of interest, and such programs have principal types that seem reasonable. In Damas and Milner's system principal types are unique up to a; in our system, because of the constraint sets in type schemes, there can be more inter- esting non-unique principal types. Above, we gave two different principal types for <. Similarly, if A = (f: ?nt, f: boot, g : boot, g: chari, then if Va with f: a, g : a. a is a principal type for some expression e with respect to A,then so is boot, because the only way to satisfy the constraint set : a, g : aJ is to let a be boot. The reader may be uneasy about the existence of multiple principal types, especially since, under our definition of >A, they are not all interderivable. In the inference aigorithm, however, it is only necessary to generate r types from a principal type, not j types. Further, any principal type of an expression can be used to derive all the r types of the expression. So multiple principal types are not a problem. These two principal types for < help to explain why we use the semantic approach to defining >A. Under the syntactic definition, Va with <:a a H boot.a a boot ?A Va with <:a a so it would appear that Va with < : a a boot. a a boot be a principal type of < so they have _ type Va with <:a. a . Besides being is not principal. But Wadler and Blott want this to arranged their type system so that < does nol have unreasonable, this clutters the type system. 24 2.2 Properties of the Type System In this section we establish a number of useful properties of the type system. We begin by showing that, roughly speaking, typing derivations are preserved under substitution. This property will be used many times in what follows. Lemma 2.4 If A H e : a then AS H e: aS. Furthermore, g?en any derivation of A H e : a, a derivation of AS H e : aS can be constructed that uses the same sequence of steps except that it inserts a (=a) step after each (V-intro) step. Proof: By induction on the length of the derivation of A H e : a. Consider the last step of the derivation: (hypoth) The derivation is simply A H x : a where x : a e A. So x : aS E AS, and ASHx:aS. (? -intro) The derivation ends with A u (x : ri H e' : A H Ax.e' : r where x does not occur in A. By induction, (A u fx : rl)S H : YS. Since (Au fx : Ti)5 = AS u (x : rS?, and since x does not occur in AS - (H -intro) can be used to give AS H ????? : rS H T'S and TS T'S = (r H (? -elim) The derivation ends with A H e': r H A H e" : r A H e' e" : r1 By induction, AS F e' : (r H T')S and AS ? e" : rS. Since (r H r')S = rS H T?5, (H -elim) can be used to give AS H ?I??! : r15. (let) The derivation ends with AFe' ?? A U (x : a?? H e" : r A F let x = e' in ??? : T where x does not occur in A. By induction, AS H : ??5 and (A U fx: ? e" : TS. Since (A U (x : a'?)S = AS U fx : a'Si and since x does not occur in AS, it follows from (let) that AS F let x = e'in e" : rS. 25 (V-intro) The derivation ends with AUCH e:r A H C[Q? := ir] AHe: Vowith C.r where Q are not free in A. Let ? be distinct type variables occurring free in neither S,nor Va with C. r ,nor A. By induction, (A u C)[a := ?S H e: r[a := and AS H C[a? := ir?]S. Now (A u C)[a? := ?S = AS u C[a? := ?S, since the a are not free in A. Also, [a:=ir?jS and [a:=?S[?:=ir?S] agree on (Both substitutions take a? `?` irjS. On any other variable ? in C, both substitutions take ?:.` 65, as no can occur in 65.) Hence and AS u C?- := ?S F e: r[a? := AS H C[a := ?S[? := irS] So, since ? are not free in AS, by (V-intro) ASHe: V?with CW:=?S.r[a:=?S By Lemma 2.3, V? with C[a :=?S.r[a :=?S a (Va with C.r)S, so by inserting an extra (=a) step we obtain ASFe:(Vawith C.T)S. (V.elim) The derivation ends with AHe: Va with C.T A H C[a? := ir?] A H e : ?[a? := ir?] By induction, ASFe:(Va-with C.T)S and 26 AS H C[a Let J3 be the alphabetically first distinct type variables occurring free in neither 5 nor Vo with C. T. Then (Vo?with C.T)S= VP with C[a:=PThS.?[o-:=ThS- By the same argument used in the (V-intro) case above, C[o? := r?]S = C[o Th?[P := So by (V-elim), and as above, AS H e: T[o := Th?[P irS], r[o? := ThS[P irS] = ir] (=?a) The derivation ends with QED AH e:a a =? a AHe:a By induction, AS H e: a'S, and by Lemma 2.2, a'S a aS. So by (=a), AS He: aS. We now begin the development of the main result of this section, a normal- form theorem for derivations in our type system. Let (V elim') be the following weakened (V-elim) rule: (V-elim') (x: Va?with C.r)eA A H C[o? := ir?] A H x : r[o := ir]. Write A H' e : a if A H e: a is derivable in the system obtained by deleting the (V-elim) rule and replacing it with the (V-elim') rule. Obviously, A H' e : a implies A H e : a. We will see that the converse holds as well, so H' derivations may be viewed as a normal form for H derivations. A similar normal-form result for Damas and Milner's type system appears in [CDDK86] and is discussed in [Tof88j. The usefulness of the restricted rules is that if A H? e : r, then the form of e uniquely determines the last rule used in the derivation: if e is x the derivation ends with (V?elim?), if e is Axe' the derivation ends with (H -intro), if e is e? e? the derivation ends with (H -elim), and if e is let x = e'in e" the derivation 27 ends with (let). In contrast, a derivation of A H e : r is much less predictable: at any point in the derivation there may be a use of (V-intro) followed by a use of (V-elim). Observe that since a (V-elim') step is equivalent to a (hypoth) step followed by a (V-elim) step, it follows immediately from Lemma 2.4 that ?` derivations are also preserved under substitution: Corollary 2.5 If A ?` e : a then AS F' e : aS. Furthermore, given any deriva- tion of A H' e : a, a derivation of AS ?` e : aS can be constructed that uses the same sequence of steps except that it inserts a (=?) step after each(V-intro) step. Before proving the normal-f6rm theorem, we show a number of auxiliary lemmas. These auxiliary lemmas, like Lemma 2.4, are proved by induction on the length of the derivation. Because the proofs are tedious, we relegate them to Appendix A. Lemma 2.6 If x does not occur in A, x ? y, and A u (x : aJ ?? y : r, then A H' y : r Proof: See Appendix A. QED Lemma 2.7 If A ?` e : a then A u B F' e : a, provided that no identifier occurring in B is A -bound or let-bound in e. Proof: See Appendix A. QED Lemma 2.8 Let B be a set of r-assumptions. If A u B H' e : a and A ?` B, then A ?` e : a Proof: See Appendix A. QED With the above lemmas in hand, we can prove the normal-form theorem for derivations: Theorem 2.9 AH e: a if and only if A F' e: a Proof: It is immediate that A H' e : a implies A H e : a, since a (V elim?) step can be replaced by a (hypoth) step followed by a (V-elim) step. We prove that A H e : a implies A H' e: a by induction on the length of the derivation of A ? e : a. All cases follow immediately from the induction hypothesis except for (V-elim). (V-elim) The derivation ends with AHe: V??with C.r A H C[? :--H--H 7r] A H e : := 7r] 28 By induction we have A H' C[? := 7r-J. Now, the derivation of A ? e Va with C. r ends with (hypoth), (V- intro), or (hypoth) We can simply use (Velim') to get AF' e: ?[a := (V-intro) The derivation ends with AUCH e: r A H C[o := AHe: Va?withC.r where a are not free in A By induction, A u C H' e : r. By Corollary 2.5, (A u C)[a := ? H' e : r[a? := 7r]. Since a are not free in A, (A u C)[a ir] = A u C[a ir]. Since A H' C[a ir], by Lemma 2.8 we have A F' e : r[a? := ir?]. (=a) The derivation ends with A H e : a' a' =? Va with C. T AFe: Va with C.r where for some P not free in Va? with C. r a' = VP with C[a? := . r[a? := Note that and C[a? := ?][? := ir?] = C[a := ir?] r[a := Th[P := ir] = r[a := ir], so the (=a) step can be dropped and we can instead use the derivation A H e: VP with C[a := P] r[a? := AFC[a?:=P][P:=ir] A H e : T[a := Th[P := ir] This is a shorter derivation, so by induction, A F' e : r[a? := ir]. 29 QED Theorem 2.9 leads to a number of immediate corollaries: Corollary 2.10 If x does not occur in A, x $ y, and Au fx : a) H y: T, then AHy:r Corollary 2.11 If A H e : a then A u B H e : a, provided that no identifier occurring in B is A -bound or let-bound in e. Corollary 2.12 Let B be a set of T -assumptions. If A u B F e: a and A F B, then A ? e: a. Henceforth we will be fairly casual about the distinction between F and H' Lemma 2.13 If A H e : a then no identifier occurring in A is A -bound or let-bound in e. Proof: See Appendix A. QED This lenima gives us the following variant of Corollary 2.11. The variant will be used in proving algorithm W0 sound. Corollary 2.14 If A F e : a then A U B H e : a, provided that all identifiers occumng in B also occur in A. We conclude this section by introducing a property that is needed to ensure that a type assumption set is, in a certain sense, well-behaved. The property is motivated by the following observation: the satisfiability condition of the (V- intro) rule prevents the derivation of `vacuous' typings A H e : VQ with C. T where C is unsatisfiable, but such vacuous typings could be present in A itself. Definition 2.3 A has satisfiable constraints if whenever (x: Vo- with C. r there exists a substitution [? := 7r?] such that A H C[? := 7r] Note that it is no real restriction to limit ourselves to assumption sets with satisfiable constraints, since any assumption with an unsatisfiable constraint set is basically useless. The essential property of assumption sets with satisfiable constraints is that any well-typed program has unquantified types; no well-typed program has only quantified types. Lemma 2.15 If A has satisfiable constraints and A H e : a, then there exists a type r such that A H e : r 30 Proof: If cr is a 7-type, there is nothing to show. Otherwise, we can strip off any final (=?) steps in the derivation A H e: a to obtain a derivation A H e : a' ending with either (hypoth) or (V-intro). In the (hypoth) case, the derivation is simply A ? x : a' where x : a' fA. Say a'is of the form VQ with C. ? ; since A has satisfiable constraints it follows that there is a substitution [Q ?] such that A ? ir]. Hence the derivation may be extended using (V-elim), giving A H x: 7[0? := 7r?] In the (V-intro) case, the derivation must end with AUC He :7 A H C[& AHe: Va?withC.? where 0 are not free in A. Again the derivation may be extended using (V-elim), giving A H e: 7[0 7r]. QED Lemma 2.16 If A has satisfiable constraints and there exists a substitution [0 it] such that A H C[a- it?], then A u fx : Va with C 7 ? has satisfiable constraints. Proof: By Corollary 2.11, we have A u tx: Va with C. 7] H C[o := it]. And if y : V? with ?1 71 f A, then since A has satisfiable constraints there exists pw\ such that A H C'[p := p?]. Using Corollary 2.11 again, we get that Au fx: Va with C.7] H C'[p := p]. QED In proving the completeness of algorithm W0 below, we must restrict our attention to assumption sets with satisfiable constraints. 2.3 Algorithm wo A fairly straightforward generalization of Milner's algorithm W [Mil78,DM82] can be used to infer principal types for expressions in our language. Algorithm W0 is given in Figure 2.2. W0(A, e) returns a triple (5, B, 7), such that ASUB He :7 Informally, 7 is the type of e, B is a set of 7-assumptions that describe all the uses of overloaded identifiers in e, and 5 is a substitution that contains refinements to the typing assumptions in A. ? We informally discussed the refinement of A by Milner's algorithm W in Chapter 1. 31 W0(A, e) is defined by cases: 1. e is x if x is overloaded in A with icy Vo?.r, return ([],fx:r[a:=Th1,r[a:=Pi) where p arenew else if (x: Vo?with C.r)eA, return ([],C[a:=Th,r[a:=Th) where p arenew else faiL 2. e is Ax.e' if x occurs in A, fail. let (Si,Bi,ri)=W0(Aufx:o?,e') where o is new; return (S1,B1,?S1 H ri) 3. e is ?I??I let (S1,B1,r1) = W0(A,e'); let (S2,B2,r2) = W0(AS1,e11); let S3 = unify(riS?,r? HO) where c is new; return (Sis2s3, B15253 U B2S3, 053) 4. e is let x = e' in ??? if x occurs in A, faiL let (S1,B1,r1) =W0(A,e'); let (B1,,a1)= ctose(ASi,Bi,ri); let (S2,B2,T2) = W0(AS1 U fx : ail,e"); return (5152, B1152 u B2, T2). Figure 2.2: Algorithm W0 32 Case 1 of algorithm W0 makes use of the least common generalization (lcg) of an overloaded identifier. 6 The lcg of an overloaded identifier x captures any common structure among the overloadings of x. For example, given the overloadings char H char H bool, real real bool, VQ with < : 0 0 H bool. seq(o) H seq(o) bool, Va,P with <: o? 0 H bool, < : H bool (OL x H (o x bool, the lcg of < is V0.o H 0 H bool, which tells us that in all of its instances < takes two arguments of the same type and returns a bool Formally, we say that r is a common generalization of Pi,... , p? if there exist substitutions Si,.. , S? such that TSj = p? for all i, and we say that r is a least common generalization of Pi,... , p? if 1. T is a common generalization of pi,..?, p?, and 2. if r1is any common generalization of pi,... , p?, there exists a substitution S such that ??5=? Finally, we say that Vo?.r is an lcg of an identifier x that is overloaded in A if r is a least common generalization of the bodies of those type schemes a with x : a E A, and 0 are the variables of r. Least common generalizations are discussed in [Rey7O], which gives an algorithm for computing them, and in [McC84j under the name least general predecessors. The "new" type variables called for in algorithm W0 are produced by a new type variable generator, which produces an unbounded sequence of distinct type variables. Before W0(A, e) is called, the new type variable generator is initialized so that it does not generate any type variables occurring free in A. Function unify, used in case 3 of W0, returns the most general unifler [Rob65, Kni89] of its arguments. That is, unify(r, r') returns a substitution U such that = r'U, failing if no such substitution exists; furthermore U has the property that for any V such that rV = r'V, V can be factored into ?V? for some V'. Function close, used in case 4 of W0 , is defined in Figure 2.3. The idea behind close is to take a derivation AuBH cr where B is a set of assumptions about overloaded identifiers and, roughly speak- ing, to apply (V-intro) as much as possible, yielding an assumption set B' and a type scheme a such that A u B' ? e : a. 6In fact the soundness and completeness of W0 do not rely on the use of the least common generalizations of the overloaded identifiers; any common generalization will do. In particular, the type Va.c can always be used, but this leads to less informative principal types. close(A, B, r): 33 let a be the type variables free in B or T but not in A; let B" be the set of constraints in B in which some oj occurs; if A has no free type variables, then if satisflable(B, A) then B' = fJ else fail else B' = return (B', Va with B". T). Figure 2.3: Function close If A has no free type variables, B' will be empty. Function satisfiable(B, A) used in close checks whether B is satisfiable with respect to A, that is, whether there exists a substitution 5 such that A H BS. We defer discussion of how satisfiable might be computed until Section 2.5. Actually, there is a considerable amount of freedom in specifying the exact behavior of close. It is possible to give fancier versions of close that try to do more simplification of the generated type a. We have, therefore, extracted the properties of close needed to prove the soundness and completeness of W0 into two lemmas, Lemma 2.17 and Lemma 2.19; this allows us to replace the simple close of Figure 2.3 by any other close that satisfies the lemmas.7 If A has no free type variables, a principal typing for e can be obtained as follows: W0(A,e) yields (S,B,7) such that AS u B H e : r. Since A has no free type variables, this means that A u B H e : T. If (B', a) = close(A, B, T) succeeds, then we will have AUB' He: a and ?? = f?, so AH e: a, and this typing will be principal. In particular, under the reasonable assumption that there are no free variables in the initial assumption set, we may weaken the condition "A has no free type variables" on the third line of ciose, replacing it with the condition "no type variable in B is free in A". The weaker condition has the advantage of allowing certain type errors to be detected sooner. 34 fix Aleq.Ax.Ay. if (null? x) true if (null? y) false if (= (carx) (cary)) (teq (cdr x) (cdr y)) (< (carx)(cary)) Figure 2.4: Example lexicographic Here is an example of a type inference using W0. Suppose that fix : Va.(a H a) H a, if : Va.boot H a a H a, --H : Va.a a H boot, true : boot, A = false : boot, car : Va.seq(a) H a, cdr : Va.seq(a) seq(a), null? : Va.seq(a) H boot, : char H char boot, _ : Va with < : a H a H boot. seq(a) H seq(a) H boot Identifier fix denotes a least fixed-point operator, which allows us to express recursion without the use of an explicit letrec construct. 8 Let lexicographic be the expression given in Figure 2.4. Function lexicographic takes two sequences x and y and tests whether x lexicographically precedes y, using ? to compare the elements of the sequences. The call W0(A, lexicographic) returns := seq(A1), n := boot, () := boot boot H boot e o+--H boot, t boot H boot ? --H seq(A1), j' := boot, v := boot H boot H boot, ,: boot, ? := boot boot, ? := A1, a := A1, p := A1, r := A1 H boot, A := A1, ? := A1, v: A1, ? boot, ? := boot boot? boot, := A1, a? := seq(A1), ? := seq(A1) H seq(A1) H boot, w := A1, := seq(A1), P1 := seq(A1) H boot, e := boot, ? := boot boot, := A1, C1 := A1, ?1 := A1, tci := A1 H boot, ni := A1, [1 := A1, vi := boot, 0 := boot, ?? := boot, 01 := boot, ri := boot, a := seq(A1) H seq(A1) H boot, Pi := seq(A1) H seq(A1) .` boot : A1 H A1 H bootj, seq(A1) H seq(A1) H boot More precisely, "letrec x = e in e',, is equivalent to "let x = fix Ax.e in e',,. See [Rey85j for further discussion of fix. 35 Then the call ctose(A, f? : A1 A1 boot?, seq(A1) H seq(Ai) boot) returns (fJ, VA1 with ? : A1 A1 H boot.seq(A1) H seq(A1) boot), giving the principal typing A H lexicographic: VA1 with < : A1 H A1 H boot. seq(Ai) H seq(A1) boot. 2.4 Properties of W0 2.4.1 Soundness of W0 First we have a lemma giving the properties needed of close in proving that W0 is sound. Lemma 2.17 If (B', a) = cThse(A,B,?) succeeds, then for any e, if AUB He: r then A u B' H e : a. Atso, every identifier occurring in B' or in the constraints of a occurs in B Proof: Suppose that (B', a) = close(A, B, r) succeeds and that A u B H e: r - There are two cases to consider: 1. A has no?free type variables. In this case satisflabte(B, A) is true, so there exists a substitution S such that A H BS. The only variables occurring in B are the a?, so we may write 5 = := 7r] without loss of generality. Since B" C B we have A H Th'[o := 7r] and A H (B --H B")[o := 7r]. Now by the definition of B", the a do not occur in B --H B", so in fact we have A H B --H B". Then, by Corollary 2.11, wehave AUB"HB--HB". Since AUB11U(B--HB11)He:?, we may apply Corollary 2.12 to yield A u B" H e : r. The a are by definition not free in A, so (V-intro) may be applied: A u B" H e: r A H B11[a? := AHe: Va?with B".r showing that AUB' He: a. 2. Ahasfreetypevariables. Let ? be new type variables not occurring in A, B, or T. By Lemma 2.4, we have (A u B)[a := p] H e : r[a := ?]. Then by Corollary 2.14, (A u 36 B)[?:=ThuBHe:r[?:=Th. Now(AuB)[a:=ThuB=AuBuB11[a:= Pi? by the definitions of ? and B". Hence (V-intro) may be applied: AuBuB11[? :=Th He: r[a := Pi AUB H B11[a? :=Pi[P := AUB He: VP with B11[o := since the P are not free in A u B Finally, since V? with B11[a? := ?. := a Va with B". r, we may use (--Ha) to get A u B H e: Va with B". r As for the second part of the lemma, it follows immediately from the fact that B' and B" are subsets of B. QED Theorem 2.18 If (5, B, r) = W0(A, e) succeeds, then AS u B H e : r. Fur- thermore, every identifier occurring in B is overloaded in A or occurs in some constraint of some assumption in A Proof: By induction on the structure of e. 1. eisx Then W0(A,e) isdefinedas: if x is overloaded in A with lcg Va?.r return ([],?x:r[a:=P]J,r[a-:=P?) where ? are new else if (x: Vc? with C.r)cA, return ([],C[o := ?], r[o Pi) where p- are new else fail. If x is overloaded in A, then (S,B,T) = ([i,fx : T[a? := Th?,r[a := Th)? so ASuB=Au(x:?[o-:=Thi. Soby(hypoth), ASuBHx:r[a:=Th. Also, every identifier occurring in B is overloaded in A. If x is not overloaded in A, then (S,B,r) = ([i,C[a := Pi,r[a? := Th)? so ASu B = AU C[a := P] By (hypoth), ASu B H x: Va? with C.r and AS U B H C[a := P]. So by a (possibly trivial) use of (V-elim), AS U B H x : r[o := Pi. Also, every identifier occurring in B occurs in a constraint of an assumption in A. 2. eisAx.e' Then W0(A,e) isdefinedas: if x occurs in A faiL let (S1, B1, Ti) w0(A U fx : 0), e') where a is new; retun? (S1, B1, oSi ri) 37 By induction, (A u fx : ai)Si u B1 H e' : ri. Also, every identifier in B1 is overloaded in A u (x : a) or occurs in some constraint of some assumption in A u (x : a). Since x does not occur in A, and since the type a has no constraints, this means that every identifier in B1 is overloaded in A or occurs in some constraint of some assumption in A. In particular, x does not occur in B1 and, therefore, x does not occur in AS1 u B1. So, since (AUtx : a))S? UB1 = AS1UB1 Ufx :aS?), we can use (?Antro) to get AS1 u B1 H Ax.e' : aS1 H 3. eise1e', Then W0(A, e) is defined as: let (51, B1, ri) = let (52, B2, r2) = w0(A51,?11) let 53 = nnify(r152, r2 a) where a is new return (515253, B15253 u B253, as3). By induction, AS1 U B1 H e' : Ti and AS1S2 u B2 H e" : T2, and every identifier occurring in B1 or in B2 is overloaded in A or occurs in some constraint of some assumption in A. Hence every identifier occurring in B1 5253 U B2 53 is overloaded in A or occurs in some constraint of some assumption in A. By Lemma 2.4, A515253 U B15253 ? : T15253 and AS1 5253 U B2S3 H e" : T2S3. So by Corollary 2.14, and AS1 5253 U B15253 U B253 H e' : T15253 A515253 U B15253 U B253 F e" : T253. By the definition of un?j??, T1S2S3 = T2S3 H a5?. Hence by (H -elim), we have A515253 U B15253 U B253 F e'e" : aS?. 4. eisletx=e1ine" Then W0(A,e) is defined as: if x occurs in A, faiL let (5i, B1, ri) = w0(A, e'); let (B1,,ai) = close(A5i, B1, r1) let (52, B2, r2) = ?v0(A51 U ?x ai),e") return (5152, B1152 U B2, r2). By induction, AS1 U B1 F e' : T1, and every identifier occurring in B1 is overloaded in A or occurs in some constraint of some assumption in A. So by Lemma 2.17, AS1 U B11 H e' : a1 and every identifier occurring in 38 B11 is overloaded in A or occurs in some constraint of some assumption in A. In particular, since x does not occur in A, x does not occur in B11 . Also by induction, (AS1 u tx : ,a1))52 u B2 F e" r2, which is the same as AS1S2 u B2 u fx : a?S?l ? e : r2, and every identifier occurring in B2 is overloaded in AS1 u ? x : a?l or occurs in some constraint of some assumption in AS1 u (x : a?J. Now x does not occur in A, and by Lemma 2.17 every identifier occurring in the constraints of al occurs in B1. Hence every identifier occurring in B2 is overloaded in A or occurs in some constraint of some assumption in A. In particular, then, x does not occur in B2. Now Lemma 2.4 and Corollary 2.14 may be applied to give AS1S2 u P11S2 u B2 F e' : a?S? and AS1S2 u P1,S2 uP2 U fx : a?S?? H e', : T2. So, since x does not occur in AS1S2 u P11S2 uP2, (let) may be used to get AS1S2uP11S2uP2Flet x=e' in e11 :r?. QED 2.4.2 Completeness of W0 Ultimately, we will prove the following principal typing result. Theorem Let A be an assumption set with satisfiable constraints and no free type variables. If e is well typed with respect to A, then (5, P, r) = W0(A, e) succeeds, (B', a) = close(A, P, r) succeeds, and the typing A ? e : a is principal. Reaching this result will take some time, however. We start with a lemma that gives the properties of close needed to establish the completeness of W0 Lemma 2.19 If AS ? PS, then (B',a) = close(A,P,r) succeeds and a is of the form Va with B". T . In addition, o+ if A has no free type variables then B' = o+ fr(a) C fv(A), and o+ B' u B" C P Proof: If A has free type variables, then close(A, P, r) succeeds. If A has no free type variables, then the assumption AS F PS becomes A F BS. Hence satisfiable(B, A) is true, and close(A, P, r) succeeds. 39 The remaining parts of the lemma are immediate from the definition of close(A, B, r). QED Lemma 2.20 If (5, B, r) = W0(A, e) succeeds, then every type variable occurring in 5, B, or r occurs free in A or else is generated by the new type variable generator. Proof: A straightforward induction on the structure of e, using properties of uni? and Lemma 2.19. QED Definition 2.4 Let A and A' be assumption sets. We say that A is stronger than A', written A ? A', if 1. A' H x: r implies A H x : r, and 2. id(A) C id(A') Roughly speaking, A ? A' means that A can do anything that A' can. One would expect, then, that the following lemma would be true. Lemma If A' H e: r, A' has satisfiable constraints, and A ? A', then A H e: T Given this lemma, we can prove the following completeness theorem for W0: Theorem If AS H e : r and AS has satisfiable constraints, then (5o, B0, ro) = W0(A, e) succeeds and there exists a substitution T such that 1. 5 = S0T, except on new type variables of W0(A, e), 2. ASHB0T,and 3. r=r0T Unfortunately the lemma appears to defy a straightforward inductive proof. The essential difficulty is in the (V-intro) case. Consider the case where the derivation A' H e: r ends with (let): A' H ?? : a A' u tx : al F e11 : r A' H let x = e' in ??? : 7 We would need to use induction somehow to show that A ? e' : ?? for some such that A u fx : ? A' u fx : al, 40 allowing us to use induction on the second hypothesis. Suppose that the deriva- tion of A' H e' : a is by (V-intro): A' u C ? : A' F C[o? := A'He': Va?with C.r' Now we would like to use induction to show that A u C H ?? : 71 But we have a serious problem: it need not be the case that A u C ? A' u C! And in fact, it need not be the case that AUC ? e' : r'. For example, let A= fx: int,y: inti and A' = tx: Va with y : a.a,y: int). Then A ? A'. But AU (y : ?) ? A'U fy : ?), and also AU fy : ?) Vx : ? although A' U fy : ?) H x : The point is that the derivation of A H e: r may have to have a very different structure from the derivation of A' H e : T, 50 it does not seem possible to `locally' modify the derivation of A' F e : T to arrive at a derivation of A H e: r. How, then, can we find a derivation of A H e : 7? The answer is to use W0 to find it. But we haven't yet shown the completeness of W0, and indeed the whole reason for introducing the lemma above was to prove the completeness theorem! So it appears necessary to combine the lemma and theorem above into a single theorem that yields both as corollaries and that allows both to be proved simultaneously. We shall now do this. Theorem 2.21 Suppose A' H e : T, A' has satisfiable constraints, and AS ? A'. Then (5o, B0, ?o) = W0(A, e) succeeds and there exists a substitution T such that 1. 5 = S0T, except on new type variables of W0(A, e), 2. ASHB0T, and 3. r = r0T Proof: By induction on the structure of e. By Theorem 2.9, A' H' e : 7 eisx By the definition of AS ? A', we have AS ?` x : 7. The last (non-trivial) step of this derivation is either (hypoth) or (V-elim'); we may write the derivation so that the last step is a (possibly trivial) use of (V-elim'). If (x:Vawiil1C.p)eA,then(x:VPwiThC[a:=ThS.p[a:=P?JS)eAS, where ? are the first distinct type variables not free in Va with C. p or in 5. Hence the derivation AS H' x: 7 ends with (x: VP with C[a:=ThS.p[a-:=ThS)eAS AS F' C[a? := ThS[P :--H--H AS H' x : p[a? := flJS[fl := where p[a := ThS[P? := = We need to show that (5o, B0, ro) = W0(A, x) succeeds and that there exists T such that 41 1. 5 = S0T, except on new type variables of W0(A, x), 2. ASHB0T,and 3. T = r0T Now, W0(A,x) is defined by if x is overloaded in A with tcg Va.r, return ([],fx:r[c:=P]J,r[?:=P?]) where ? are new else if (x: Va with C.T)fA, return ([],C[a? P], r[a Th) where ? are new else fail. If x is overloaded in A with lcg V?.p0 then (50,B0,T0) = W0(A,x) succeeds with So = [], B0 = fx po[? := ?), and To = po[? := where ? are new. Since V?.p0 is the lcg of x, ? are the only vari- ables in po and there exist ? such that po[? := = p. Let T be S?[?:=?[?:=ThS[P:=ir]]. Then So 1. T0T definition» po[? := ?(S ? := := P]S[P := 7rjj only ? occur in poK := poK? := := := ThS[P := only ? occur in po » poK? := := ThS[P := ir]] only ? occur in po » poK? := 4)Th[a := ThS[P := ir] by above» :=fl]S[P:=ir?] by above» S0T = 5 ? := := ThS[P := irfi = 5, except on ?. That is, S0T = 5, except on the new type variables of W0(A, x) 2. Since B0T= fx : ToTi = : ri, it follows that ASH B0T. 3. r0T = If x is not overloaded in A, then (So, B0, To) = W0(A, x) succeeds with So = [], B0 = := ?, and To = p[a? := ?, where ? are new. Observe that [?:=?(S?[?:=ir-]) and [?:=ThS[P:=ir] agree on C and on p. (The only variables in C or p are the a and variables e not among or ?. Both substitutions map a? i,' irj and ? 42 Let T be S?[S:=?. Then 1. SoT=S?[?:=?=S,excepton ?. That is, SoT=S,excepton the new type variables of W0(A, x). 2. Also, Hence AS H B0T 3. Finally, B0T definition» ? by above observation» ThS[P := T0T definition» ? by above observation» eisAx.e' The last (non-trivial) step of the derivation of A' F' e : r must be (H - intro): A' u (x : T11 H' e' : A' F' Ax.e' : H T11 where x does not occur in ?? We must show that (5o, B0, To) = W0(A, Ax.e') succeeds and that there exists T such that 1 5 = S0T, except on new type variables of ?V0(A, Ax.e'), 2. AS?B0T,and 3. T1 H T11 = T0T. Now, W0(A,Ax.e') is defined by if x occurs in A, fail. let (S1, B1, r1) = w0(A U ?x : aJ, e') where a is flew; return (S1,B1,aS1 ri) Since x does not occur in A' and (by AS ? A') ?d(AS) c id(A'), it follows that x does not occur in AS This implies that x does not occur in A, so the first line does not fail. 43 Now we wish to use induction to show that the recursive call succeeds. The new type variable OL is not free in A, so AS u fx : r'J (A u fx: oJ)(S ? [a By Lemma 2.16, A'Ufx : r'J has satisfiable constraints. Next we argue that ASUfx : ? A'Ufx : Y). Clearly, id(ASUfx : C ?ct(A'ufx : Now suppose that A'u (x : r1i H y: p. If y # x, then by Corollary 2.10, A' H y : p. Since AS ? A' we have AS H y : p and then by Corollary 2.11, AS u fx : r'J H y : p. On the other hand, if y x,then the derivation A' u fx : Y? F' y : p must be by (hypoth) hence p = r' So by (hypoth), ASU tx : Y? H y : p. We have shown that --H A' u fx Y? F : r11, --H A' u tx : r'i has satisfiable constraints, and --H (Aufx : ai)(S? [0= r']) ? A'u fx : r'1 So by induction, (Si, B1, ri) = W0(AUfx : a), e') succeeds and there exists T1 such that 1. 5 ? [a := = S1T1, except on new variables of H70(A u (x : a), e'), 2. (AUfx:a))(S?[a:=Y1)FBiTi,and 3. Y' = r1T1 So (50,B0,r0) = W0(A,Ax.e') succeeds with So = Si, B0 = B1, and To = aS? H Let T be T1. Then 1. Observe that S0T --H A a'. Suppose that a' >A p. Then by the definition of >A it follows that (V-elim) may be used to derive A H e p. So by Corollary 2.22 again, there exists T' such that 1. [? = ST', except on the new type variables of W0(A, e), 2. A H BT', and 3. p = rT'. Since B" C B we have A H B"T'. Notice also that all of the variables occurring in B11 or in 7 are among the ??, so by restricting T' to the ? we obtain a substitution [? := ? such that A H B11[c? := ? and p = r[a := ?. This shows that VQ with B". r >A p, and hence that Vo with B" r >A a'. So AHe: Va with B".r is principal. QED 2.5 Limitative Results Recall that in our definition of close(A, B, r) in Section 2.3, we made use of a function satisfiable(B, A) without indicating how it might be computed. We address that omission in this section. Given a set B of r-assumptions and an assumption set A, satisfiable(B, A) returns true if B is satisfiable with respect to A (that is, if there exists a substitution 5 such that A H BS) and returns false otherwise. Unfortunately, the satisfiability problem turns out to be undecidable. Theorem 2.25 Given an assumption set A and a set B of r -assumptions, it is undecidable whether B is satisfiabte with respect to A 53 Proof: It is easy to reduce the Post Correspondence Problem (PCP) [HU79] to the satisfiability problem. We present the reduction by means of an example. Suppose we are given the PCP instance xi = 10 yi = 101 X2 = 011 Y2 = 11 X3 = 110 y? = where ? denotes the empty string. We will use type constants 0, 1, and $ and a right-associative binary type constructor ??. Define Apcp = p: (1 0) (1 H 0 H 1), p : (0 1 H 1) (1 1), p: (1 H 1 H 0 $) H p: Va,Pwithp:??P. p: V?,P with p: ? H p: Vo,P with p: Q H 0 H a) H (1 H 0 H 1 H 1 H 1 a) H (1 1 H 1 0 H a) H Now consider whether fp: a a) is satisfiable with respect to Apep This will be true if and only if there is some r such that Apep ? p : r H r But Apcp gives p precisely all types of the form 7r H iri, where 7r is obtained by concatenating various Xj `5 and 7r? is obtained by concatenating the corresponding y? ???9 Hence ?p : a H a) is satisfiable with respect to Apcp precisely when the given PCP instance has a solution. QED It is conceivable that there is some way to do type inference without using function satisflable(B, A), but such hopes are quickly dashed by the following corollary. Corollary 2.26 Given an assumption set A and an expression e, it is undecid- able whether e is well typed with respect to A Proof: Again we use a reduction ftom PCP. Define Apcp as above, and consider whether the expression (Af.Ax.f(f x)) p is well typed with respect to Apcp. Now, Af. Ax.f(f x) has principal type Va.(a H a) H (a H a). Hence (Af.Ax.f(f x)) p is well typed with respect to Apcp if and only if p has some type of the form r r, which in turn holds if and only if the given PCP instance has a solution. 10 QED Another easy corollary is that the instance relation >?A is undecidable. Possibly ir and Ir' have a $ tacked on the end. 10We remark in passing that the expression (AJ.Ax.f(f x))p cannot be replaced by the simpler expression Ax.p(p x) in this proof. The problem with the simpler expression is that the two occurrences of p are not forced to have the same type. 54 Corollary 2.27 Given A, a, and r, it is undecidable whether a >?A T Proof: Define Apcp as above; then Va with p: a H a bool >Apcp bool if and only if the given PCP instance has a solution. QED It might appear that the key to all of these undecidability results is the neces- sity of `guessing': for example, to determine whether fp : a H al is satisfiable we must guess how a should be instantiated. This suggests that if we arrange to eliminate such guessing, perhaps undecidability will be avoided. To this end, we can define the class of coupled type schemes: a type scheme Va? with C. r is said to be coupled if every type variable occurring in C occurs also in r. For example, the type Va with p: a . a. bool used in the proof of Corollary 2.27 is uncoupled. We furthermore say that an assumption set A is coupled if it contains only coupled assumptions. We also require the notion of a nonoverlapping assumption set. We say that type schemes a and a' overlap if (after renaming to eliminate any common bound type variables) their bodies are unifiable. Then we say that an assumption set A is nonoverlapping if A contains no two assumptions x: a and x: ?? with a and a' overlapping. Finally we say that a type T is ground if it contains no occurrences of type variables, and an assumption x: r is ground if r is ground. If A is coupled and nonoverlapping and B contains only ground assumptions, then no guessing is involved in verifying the satisfiability of B with respect to A since B contains only ground assumptions, B is satisfiable if and only if A ? B, and we can verify A ? B by "working backwards" in a completely deterministic manner. For example, if A = (c: char, c: Va with c: a seq(a)) then we can reason A H (c: seq(seq(char))J A ? (c: seq(char)? A F fc: chari. More formally, we can verify that A H B as follows: 55 while B $ f? do choose x: T ill B find an assumption x: V? with C . p in A such that for some 5, PS = if none, then answer `no'; B --H : ?J)uCS; od; answer `yes'. Because of the restriction to nonoverlapping and coupled assumptions, there is always a unique assumption to apply next, and B always contains only ground assumptions. Notice, however, that if A = fc: V? with c: seq(c) . c ?, then an infinite branch will be generated when we attempt to verify that A H tc: chari, so our procedure is not guaranteed to terminate. One might imagine that such infinite branches can somehow be detected and avoided, but, surprisingly, this is not so. Theorem 2.28 Given a coupThd, nonovertapping assnmption set A and a gro?nd assumption x : T, it is undecidable whether A F x : T. Proof: We reduce the problem of determining whether a deterministic Turing Machine halts on empty input [HU79] to this problem. Suppose we are given a Turing Machine M = (Q,?(),1?,to,1,B?,?qo,B,?q??), where o+ Q is the set of states, o+ ?O, 1? is the input alphabet, o+ t(),1,B) is the tape alphabet, o+ ?:QxtQ1,BJ?QxtQ1,B1xtL,R1, o+ qo is the start state, o+ B is the blank symbol, o+ q? is the unique halting state. The idea is to encode instantaneous descriptions (IDs) of M as types and to define a set of type assumptions Ahalt so that Ahalt H h : p if and only if p encodes an ID from which M eventually halts. We need just one identifier h, a binary type constructor ??, and a set of type constants Q u to, 1, B, ?J. We encode IDs as follows: OlBqlO is encoded as H 1 H 0 H q H (1 0 ?), 56 and in general, for cr1 and cr? in ?O, 1, Bi*, crlqcr2 is encoded as reverse H cri q T2, where if OL = ....... Xn, n > 0, then cr = X1 X2 ... Next, we observe that M eventually halts from ID if and only if either o+ ID is a halting ID, or o+ M eventually halts from the successor of ID. We include assumptions in Ahalt to deal with these two possibilities. First, to deal with halting IDs, we include h : Vcr,P.cr H q? Next we want to express" h : ID if h : successor( ID)". Suppose that ?q, X) = Y, R). We model this by including h : OL H q H H ?) if h : H cr) H H which in our official syntax is h: VQ? with h (YH cr) Hq' H ?.cr? q? H fi) In addition, if x = B then we also include h : cr H q H ? if h: (Y H 0) H e. Similarly, if ?(q, X) = (q', Y, L), then for each Z in the tape alphabet we include h: (Z H cr) q (X H p) if h : cr H H Y H and, if X = h: (Z H cr) q e if h : cr H Y H It follows, then, that Ahalt F h : e H e if and only if M halts on e. Furthermore, Ahalt is coupled and nonoverlapping. QED In Section 2.6 we present a set of restrictions that do make the satisfiabil- ity problem decidable. First, however, we digress to mention an application of Theorem 2.28 to logic and logic programming. 57 2.5.1 A Logical Digression As we remarked earlier, our type assumptions can be rephrased as Horn clauses [Llo84J. For each identifier x, we introduce a unary predicate symbol Tx with the intention that Tx(r) means x : r. Then the type assumption x: Va with x: a, y : a H a. set(a) is represented by the Horn clause Tx(set(a)) & T?(a) A T?(a H a). The essential property of the translation is this: if A* denotes the translation of A, then AH x:r if and only if A* U ffalse & Tx(r)i is unsatisfiable. Furthermore, our definitions of coupled and nonoverlapping can be applied in the obvious way to Horn clauses. So we have the following corollary to Theorem 2.28. Corollary 2.29 It is undecidable whether a set of coupled, nonoverlappiny Horn clauses is satisfiable. This corollary has consequences for logic programming as well: the set of all logic programs that never require backtracking in their execution includes the class of all sets of coupled, nonoverlapping Horn clauses. Hence the possibility of nontermination cannot be avoided in logic programming, even in situations where no backtracking can arise. 2.6 Restricted Forms of Overloading In this section, we impose restrictions on the forms of overloading allowed; our goal is to make the satisfiability problem decidable, which in turn will make the typability problem decidable. We saw in Section 2.5 that our assumption sets are expressive enough to encode the Post Correspondence Problem and the Halting Problem. But the examples of overloading that we care about in practice do not require nearly so much power. Consider the assumptions for ? our typical interesting example of overloading: char H char H bool, real H real H bool, ?: Va with ? : a a H bool. seq(a) H seq(a) bool <:Va,? with <: a Ha H bool, < : H bool. (a x ?) H (a x ?) H bool 58 The effect of these assumptions may be stated thus: the types of < are of the form r H T H bool; by the first rule r may be char, by the second rule r may be real, by the third rule r may be seq(r') if r may be r1, and by the fourth rule r may be r? x r11 if r may be T1 and T11. That is < has exactly those types of the form T H T H bool where r is any type built from the constructors real, char, seq, and x. In this situation, we can do better than our usual implicit representation of the types for < in fact we could use the explicit representation Vajchar,real,seq,xj?? H a H bool, associating the constructor set (char, real, seq, x 1 with a to express the fact that a may only be instantiated with types built from those constructors. Fur- thermore, we will see that this explicit representation of the types of < is very useful in solving the satisfiability problem. We now make these ideas precise. Definition 2.5 We say that x is overloaded by constructors in A if the lcg of x in A is of the form Va.r and if for every assumption x : V? with C. p in A, o+ p = r[a := x(P)], for some type constructor ?, and o+ C = tx : r[a := PieP1. Furthermore, we say that the type constructor set of x in A is I A contains an assumption x: V? with C. T[a := x(P)] 1 For example, under the assumptions given above < is overloaded by constructors and has type constructor set f char, real, seq, Lemma 2.30 If x is overloaded by constructors in A with lcg Va.r and type constructor set X,then A H x : p if and only if p is of the form r[a := 7r] and 7r is a type built from the constructors in X Proof: The `if' direction is a straightforward induction on the structure of ir. The `only if' direction is a straightforward induction on the length of the derivation of A H' x : p. QED Definition 2.6 We say that A is an overloading by constructors if o+ every identifier overloaded in A is overloaded by constructors and o+ for every constraint x : p in an assumption in A, x is overloaded in A and p ? an tnstance of the lcg of x 59 We now argue that if A is an overloading by constructors, then the satis- fiability problem can be solved efficiently. For simplicity, however, we restrict satisfiable(B, A) to constraint sets B generated by W0; this is justified by the fact that close calls satisfiable only on constraint sets generated by W0. Now, if A is an overloading by constructors, then a simple inductive argument shows that if (5, B, r) = w0(A, e), then B contains only constraints of the form x : p where x is overloaded in A and p is an instance of the lcg of x. Hence we restrict our attention to constraint sets of this form. Let B be a constraint set containing only constraints of the form x : p where x is overloaded in A and p is an instance of the lcg of x. Let x : p be a constraint in B. By assumption, p = rx[a := 7r] where Va.rx is the icg of x in A, so by Lemma 2.30, A H x : pS if and only if 7r5 is a type constructed from Xx,the type constructor set of x. Examine ir; if it contains any type constructor not in Xx, then B is unsatisfiable. Otherwise, 5 satisfies x : p if and only if 5 instantiates all variables in ir to types constructed from the constructors in Xx. In this way, the constraint x : p in B associates the constructor set Xx with each variable occurring in p. Now, for each variable P in B, take the intersection of all the constructor sets thus associated with P; this gives explicitly the set of possible instantiations of p that satisfy B in particular, there is some satisfying instantiation of p if and only if the intersection contains a 0-ary type constructor. Hence, B is satisfiable if and only if every variable in B has an associated constructor set containing a 0-ary type constructor. Clearly, this procedure can be done in polynomial time. There is a natural example of overloading for which the restriction to over- loading by constructors is too severe. The example, due to Dennis Volpano, is matrix multiplication: for matrices to be multiplied it is necessary that the el- ements of the matrices can be multiplied and also added, for we need to form inner products. Hence we would like to use the assumption * : Va with + : a H a H a, * : a H a H a matrnx(a) H matmx(a) H matrnx(a), but this is not an overloading by constructors. We conjecture, however, that the satisfiability problem remains decidable when the second part of the definition of `overloaded by constructors' is relaxed to C?(x:r[a:=Pj] PiePi, which permits the above matrix multiplication assumption. Further research into the satisfiability problem is described in [VS91]. 60 2.7 Conclusion We have shown that overloading may be combined with Hindley-Milner-Damas polymorphism in a natural way that preserves the principal typing property and type inference. However, certain restrictions on overloading need to be imposed to avoid undecidability. Chapter 3 subtyping In this chapter we develop the theory of polymorphism in the presence of both overloading and subtyping. Our new type system is an extension of the type system of Chapter 2, so this chapter will parallel the development of Chapter 2, preserving as many of the results as possible. 3.1 The Type System One approach to subtyping is to use explicit type conversions, thereby eliminating the need to change the type system at all. For example, we can indicate that int is a subtype of real simply by defining a conversion function c: int real. The trouble with this approach is that it limits polymorphism. Consider, for example, the function twice, defined as Af.Ax.f(fx). Intuitively, the application of twice to a function g: real H int should be well typed. But if subtyping is achieved solely through explicit type conversion, this is not so; indeed, for the application twiceg to be well typed, we must change the definition of twice to Af.Ax.f(c(f x)). But now twice cannot be applied to a function of type char H char. In general, the use of explicit type conversions forces programs to be overspecialized. Instead, our approach to subtyping is to augment the type system with a new kind of assertion. In addition to typings e : a, we have inctusions r C r1. The inclusion T C T1 asserts that r is a subtype of r'. Inclusions are incorporated into the type system in four ways: 1. Inclusions may occur in constraint sets of type schemes. 2. Inclusions may occur in assumption sets. 3. There are new rules for proving judgements of the form A ? r C ?? 4. Finally, the new typing rule 61 62 AFe:? A ? r C T1 A H e: links the inclusion sublogic with the typing sublogic. 3.1.1 Types and Type Schemes Types are just as in Chapter 2; type schemes are now defined by a:: Vo1,...,?n with Cl,...,Cm.T, where each constraint Ci is either a typing x : p or an inclusion p C p'. We say that a type is atomic if it is a type constant (that is, a 0-ary type constructor) or a type variable. 3.1.2 Substitution and a -equivalence A substitution 5 may be applied to an inclusion r C r', yielding the inclusion (rS) C All the lemmas about a -equivalence given in Section 2.1.2 carry over to our richer set of type schemes, without modification. 3.1.3 The Typing Rules A type assumption set A may now contain inclusions r C r' as well as typings x : a. The notion of r -assumption is extended to include inclusions T C r1 as well as typings of the form x : T. All the typing rules given in Figure 2.1 are retained in the new system. In addition, there are new rules given in Figure 3.1. The first five rules allow in- clusion judgements to be proved. Rule (hypoth) allows inclusion assumptions to be used; rules (reflex) and (trans) assert that C is reflexive and transitive. Next, there are rules expressing the well-known monotonicities of the various type constructors [Rey80,Car84,Rey85]. For example, H is antimonotonic in its first argument and monotonic in its second argument. The name ((--H) H compactly represents this information. Additional rules, such as (set(+)), will be introduced as needed. The last rule, (C?), says that an expression of type r has any supertype of r as well. As an example, we derive the principal typing fJHAf.Ax.f(fx): Va,Pwith ?C?a.(a?P)?(a?P). We have tP C a, f: a ?, x: a) H f: a H (3.1) 63 (hypoth) (reflex) (trans) A H r C r', if (r C T') E A AFTCT A H T C r' A F r1 C r11 A H T C T11 A F T1 C r A H p C p' A F (r H p) C (T' H p1) A H r C r1 A H seq(r) C seq(Y) A ? r C T1 A F e : r1 Figure 3.1: Additional Rules for Subtyping 64 by (hypoth), by (hypoth), C a, f : a x : aJ H x a fPCQ f:a?P, x:alH(fx):P by (? -elim) on (3.1) and (3.2), by (hypoth), C a, f: a H x: aJ H p c a Ca, f: a H x: a) H (f x) : a by (C?) on (3.3) and (3.4), fPCQ f:a??, x:a)Hf(fx):p by (H -elim) on (3.1) and (3.5), fPCQ f:a?PJFAx.Afx):a?P by (?? -intro) on (3.6), fP C a) F Af.Ax.f(f x) (a P) H (a H by (H -intro) on (3.7), by (reflex), and finally f)FAfAx.f(fx):V?PwithPC?a.(a?P)?(a?P) (3.2) (3.3) (3.4) (3.5) (3.6) (3.7) (3.8) (3.9) (3.10) by (V-intro) on (3.8) and (3.9). Recall that, without subtyping, the principal type of Af. Ax.f(f x) is simply Va.(a H a) H (a a). This illustrates that adding subtyping to a type system has more pervasive effects than does adding overloading the principal type of a program that uses no overloaded identifiers is unaffected by the presence of overloading, but the principal type of every program is potentially changed by the presence of subtyping. 3.1.4 The Instance Relation The instance relation >A needs to be refined to account for subtyping. What we want, essentially, is that a r if and only if A u (x: a) H x : r, where x is any identifier not occurring in A. Definition 3.1 (Va? with C. r) >A T1 ?f there ? a substitvtThn [a? r-] such that o+ AHC[a:=ir] and o+ A H r[a? 7r] C r1. 65 3.2 Properties of the Type System In this section we show that the properties of the type system of Chapter 2 are not disturbed by the addition of subtyping. We begin by showing a number of useful properties of the inclusion sublogic; fortunately, inclusions have simpler behavior than do typings, so the proofs are easier. Lemma 3.1 If A H T C r', then AS H TS C T'S. Furthermore, the demvation of AS H rS C r1S uses the same sequence of steps as the dernvat?on of A H r C r1. Proof: By induction on the length of the derivation of A F T C r1. Consider the last step of the derivation: (hypoth) The derivation is simply A ? r C r' where (T C T') E A. So (TS C r'S) ? AS, and AS F rS C YS by (hypoth). (reflex) By (reflex), AS F rS C TS (trans) The derivation ends with A ? r C r' A H r' C r'1 A H T C r" By induction, AS F rS C r'S and AS H T'S C r11S, so by (trans), AS F TS C r"S (+)) The derivation ends with A H r1 C r A H p C PI A H (r H p) C (r' H PI) By induction, ASH T'S Cr5 and ASH pS C p'S, so by ((--H) H AS H (rS H p5) C (r'S H p15) Other type constructors are handled in the same way. QED Lemma 3.2 If A u fx : al H r C r1, then A H r C r1 Proof: By a straightforward induction on the length of the derivation of Au (x: a) H r C r1. QED Lemma 3.3 If A H r C r',then A u B H r C r' 66 Proof: By induction on the length of the derivation of A H 7 ? r'. QED Lemma 3.4 If AUB ? 7 C 7' and A H B, then A H 7Cr' Proof: Yet another straightforward induction, this time on the length of the derivation of AuBHrCr'. QED Now we show that the properties proved in Section 2.2 still hold in our new system with subtyping. Here is the counterpart to Lemma 2.4: Lemma 3.5 If A H e : CT then AS H e: aS. Furthermore, gtven any derivation of A H e : CT, a derivation of AS H e : CTS can be constructed that uses the same sequence of steps except that it inserts a (=a) step after each (V -intro) step. Proof: The proof of Lemma 2.4 suffices, except that we must consider the case when the derivation of A H e : CT ends with (C). (c?) The derivation ends with QED AHe:r A H r C r' A F e : By induction, AS H e : 75, and by Lemma 3.1, AS H rS C r'S. So by (c), ASHe:r'S Again, our major goal is to prove a normal-form theorem for derivations. Define rule (V-elim') as in Chapter 2 (see page 26), and say A H' e : CT and A H' r C r' if these can be derived in the system obtained by deleting (V- elim) and replacing it with (V-elim'). Because H' does not restrict the inclusion sublogic in any way, the following lemma is immediate. Lemma 3.6 A H r C r' if and only if A F' r C r'. Here is the counterpart to Corollary 2.5: Corollary 3.7 If A H' e : CT then AS H' e : CTS. Furthermore, given any deriva- tion of A H' e : CT, a derivation of AS ?` e : CTS can be constructed that uses the same sequence of steps except that it inserts a (--H=?) step after each (V-intro) step. The counterparts to Lemmas 2.6, 2.7, and 2.8 are given next; their straight- forward proofs are given in Appendix A. Lemma 3.8 If x does not occur in A, x ? y, and A u (x : a? K' y : 7, then A ?` y : 7. 67 Lemma 3.9 If A H' e : a then A u B H' e : a, provided that no identifier occurring in B is A -bound or let-bound in e. Lemma 3.10 Let B be a set of r -assumptions. If A u B Y e : a and A F' B, then A ?? e : a. With these lemmas, we can now show the counterpart to Theorern 2.9. Theorem 3.11 AH e : a if and only if AH' e: a Proof: The proof of Theorem 2.9 suffices, except that when the derivation of A H e : a ends with (c?), we use the fact that A H r C r' if and only if AH'rCr' QED As in Chapter 2, we get the following corollaries: Corollary 3.12 If x does not occur in A, x $ y, and A u fx : al H y : r,then A?y:r Corollary 3.13 If A ? e : a then A u B F e : a, provided that no identifler occurring in B is A -bound or let-bound in e Corollary 3.14 Let B be a set of r -assumptions. If A u B H e : a and A H B then A ? e: a. Lemma 3.15 If A F e : a then no identifier occurring in A is A -bound or let-bound in e. Corollary 3.16 If A H e : a then A u B F e : a, provided that all identifiers occurnng in B also occur in A. As in Chapter 2, we define the notion of an assumption set with satisfiable constraints; both of the lemmas about assumption sets with satisfiable constraints carry over without change. Lemma 3.17 If A has satisfiable constraints and A ? e : a, then there exists a type r such that A F e: r Lemma 3.18 If A has satisfiable constraints and there exists a substitution [ot r] such that A ? C[? 7r], then A u tx : Va? with C. r ? has satisfiable constraints. Algorithm Wos and the new close given below make certain demands about the inclusions in the assumption sets that they are given. In particular, they disallow assumptions like int C (int H int) in which the two sides of the inclusion do not have the same `shape'. Furthermore, they disallow `cyclic' sets of inclusions such as bool C int together with int C bool. The precise restrictions are given in the following definitions. A constant inclusion is an inclusion of the form c C d where c and d are type constants (i.e. 0-ary type constructors). 68 Definition 3.2 An asstmption set A is said to have acceptable inclusions if o+ A contains only constant inclusions and o+ the transitive closure of the inclusions in A is antisymmetric. We now establish a few properties of assumption sets with acceptable inchi- 510115. Recall that atomic types are type constants or type variables. Definition 3.3 Types T and r' have the same shape if either o+ r and r' are atomic or o+ r=x(ri,...,Tn), Y=?(???...?r?I)? where ? isan n-arytypeconstruc- tor n > 1, and for all i, ri and ?j? have the same shape. This definition appears in [Mit84] under the name `matching', and also in [Sta88J and [FM9oj. Note that the `same shape' relation is an equivalence relation. Define an atomic inclusion to be an inclusion of the form r C r1 where r and TI are atomic. Any constant inclusion is an atomic inclusion, so the following lemmas apply to any assumption set with acceptable inclusions. Lemma 3.19 If A contains only atomic inclusions and A H T C r' then r and r' have the same shape. Proof: By induction on the length of the derivation of A H r C r1. QED Lemma 3.20 If A contains only atomic inclusions and A H r p C T1 . PI then A ? r' C r and A H p C PI Proof: By induction on the length of the derivation of A F T H p C r' p'. Consider the last step of the derivation. Since A contains only atomic inclusions, the last step cannot be (hypoth). Hence the last step is (reflex), (trans), or ((--H) H (+)). In the (reflex) and ((--H) H (+)) cases, the result follows immediately. Suppose the derivation ends with (trans): A ? (T H P) C ? A H ? C (T1 H A H (r H P) C (r1 H By Lemma 3.19, T H P and ir have the same shape, so 7r is of the form irI H By induction, we have A ? ?` C r, A H P C ?ll, A F T1 C 7rI and A H irIl c P1 Hence by (trans) we have A H TI C T and A ? P C P1. QED In the same way, one can prove similar lemmas for the other type constructors. Lemma 3.21 If A has acceptable inclusions, A ? T C T1 and A H r1 C r then T = T1 69 Proof: Since A contains only atomic inclusions, r and TI have the same shape. Hence we may use induction on the structure of r and r'. If r and r' are atomic, then both r C r' and T1 C r are in the reflexive transitive closure of the inclusions in A. Since by assumption the transitive closure of the inclusions in A is antisymmetric, it follows that r = Now suppose that T = T1 H T2 and r' = H T21 By Lemma 3.20, we have A H 4 C ri, A ? r2 C r21, A ? Ti C r11, and A H r21 C r2. So by induction, ri = 4 and T2 = r21. Other type constructors are handled similarly. QED 3.3 Algorithm W05 Algorithm Wos is given in Figure 3.2. The algorithm differs from W0 in two ways. First, there is a small change to the let case; close(A, B, r) now returns a substitution 5 as well as a constraint set B' and a type scheme a. The idea is that close may discover that some of the type variables in B can be instantiated in only one way if B is to be satisfied; any such instantiations are returned in the substitution ? ? The major departure from W0 is in the case of an application e1c". Intuitively, W08 returns the smallest possible type for an expression. Normally, such a type can be used in a derivation in place of a larger type. The one exception is in the (H -elim) case, where the type of the argument e" is required to be the same as the domain of the function e'; in this case, it may be necessary to pass from the type found by W08 for the argument e" to a supertype. We now discuss close. For now, we trivially modify the close of Figure 2.3 so that it always returns the identity substitution. In Section 3.6 we will give a fancy close and prove that it satisfies the two lemmas needed to establish the soundness and completeness of W08 3.4 Properties of W05 3.4.1 Soundness of W08 The soundness of close is given by the following lemma. Lemma 3.22 If (5, B', a) = close(A, B, r) succeeds, then for any e, if A u B H e : r then AS u B' H e : a. Also, every identifier occurring in B' or in the constraints of a occurs in B 1 ?0 could also be modified to use a version of close that returns a substitution, but without subtyping it doesn't seem important to do so. 70 W08(A, e) is defined by cases: 1. e is x if x is overloaded in A with lcg Va.?, return ([],tx:r[c-:=PJ1,r[?:=Th) where p arenew else if (x: V?with C.T)EA, return ([],C[?:=Th,r[?:=Th) where ? are new fail. else 2. e is ????? if x occurs in A, fail. let (Si,Bi,ri) = Wos(AU (x : al,e') where o is new; return (Si,Bi,aSi H ri) 3. e is e'e" let (Si,Bi,ri) = W0s(A,e'); let (52, B2, r2) = W08(AS1, e"); let 53 = unifit(T152,? H ?) where ? and ? are new; return (s1s2s3,B1s253uB2s3u fr253 C ?531,P?3) 4. e is let x = e' in e'1 if x occurs in A, faiL let (51,B1,r1) = let (52,B11,ai) = close(AS1,Bi,ri); let (53, B2, T2) = Wos(ASiS2 U fx : ?`), e11) return (S1S2S3,B1,S3 uB2,r2). Figure 3.2: Algorithm ??os 71 Next we give the soundness of W08; the proof is very similar to the proof of Theorem 2.18. Theorem 3.23 If (5, B, r) = W08(A, e) succeeds, then AS u B F e : r. Fur- thermore, every identifler oCcurring in B is overloaded in A or occurs 2n some constraint of some assumption in A 3.4.2 Completeness of Wos The properties of close needed to prove the completeness of W05 are extracted more carefully here than they were in Chapter 2, thereby giving close more freedom to do type simplification. This freedom will be exploited in Section 3.6. Lemma 3.24 Suppose that A has acceptable inclusions and AR H BR. Then (5, ??, a) = close(A, B, r) succeeds and o+ if A has no free type variables then B' = o+ fv(a) C fv(AS), and o+ there exists T such that 1. R=ST, 2. ARHB'T,and 3. aT>??TR. The next two lemmas have straightforward inductive proofs. Lemma 3.25 If (5, B', a) = close(A, B, r) succeeds, then every type variable oc- curring free in 5, B', or a occurs free in A, B, or T or else is generated by the new type variable generator. Lemma 3.26 If (5, B, T) = Wos(A, e) succeeds, then every type variable occur- ring in 5, B. or r occurs free in A or else is generated by the new type variable generator. The definition of A ? A' needs to be revised to account for inclusions; we simply demand that A and ?? contain the same inclusions. Definition 3.4 Let A and A' be assumption sets. We say that A is stronger than A', written A ? A', if 1. A' H x: r implies A F x : r, 2. id(A) c id(A'), and 3. A and A' contain the same inclusions. We now show the completeness of W05 72 Theorem 3.27 Suppose that A' H e : r, A' has satisfiable constraints, AS ? A' and A has acceptable inclusions. Then (5o, B0, ro) = Wos(A, e) succeeds and there exists a substitution T such that 1. 5 = S0T, except on new type variables of Wos(A, e), 2. ASHB0T,and 3. AS ? r0T C r Proof: By induction on the structure of e. By Theorem 3.11, A' H' e: r eisx By the definition of AS ? A', we have AS ?` x r. Without loss of gener- ality, we may assume that the derivation of AS H' x : r ends with a (possi- bly trivial) use of (V-elim') followed by a (possibly trivial) use of (c?). If (x:VcwithC.p)eA,then(x:VPwitbC[o?:=ThS.p[a:=ThS)?AS, where ? are the first distinct type variables not free in Va with C. p or in 5. Hence the derivation AS ?? x: T ends with (x: VP with C[a-:=ThS.p[o-:=ThS)eAS AS F' C[a := P]S[P := AS H' x : p[a? := P]S[P := AS H' p[a := ThS[P := r AS F' x : We need to show that (5o, B0, ro) = W08(A, x) succeeds and that there exists T such that 1. 5 = S0T, except on new type variables of ??os(A, x), 2. ASHB0T,and 3. AS?r0TCr Now, Wos(A,x) is defined by if x is overloaded in A with Icg Vc.r, return ([],?x: P]), r[a? Pi) where ? are new else if (x: Va? with C.r)?A, return ([],C[? P], r[a P]) where ? are new else faiL If x is overloaded in A with lcg V?.p0, then (50,B0,r0) = Wos(A,x) succeeds with So = [], B0 = tx : po[? := ??, and ro = po[? := ?, where are new. Since V?.p0 is the lcg of x, ? are the only variables in po and there exist ? such that po[? := = p. Let 73 Then So 1. To', As1Th T1T3 Now, AS1 S2T2 by first use of Lemma 3.24 above» AS1T1 by part 1 of the first use of induction above» AS by part 1 of the second use of induction above» A51T3 by second use of Lemma 3.24 above» AS1 S2T4 Hence T2 and T4 are equal when restricted to the free variables of AS1 52. Since, by Lemma 3.24, fr(a?) C fv(AS1S2), it follows that a1T2 = a?Th. So, by part 3 of the second use of Lemma 3.24 above, a1T2 >?As r1T3. Write a1T2 in the form Va with D. ?. Then there exists a substitution ? such that AS H D[a := and AS ? := C r1T3. 82 Using Corollary 3.13 and Lemma 3.3, then, we have the following derivation: ASUfx:a1T2JHx: VQwith D.? by (hypoth), by above, by (V-elim), by above, by(C?), AS u (x : a1T21 F D[? := ASu fx : a1T21 F x: := ff1 AS u fx : a1T21 H ?[a := C r1T3 AS u fx : a1T21 F x : r1T3 AS u fx : a1T2? F T1T3 C p by part 3 of the second use of induction above, and finally ASu fx :a1T2lF x:p by (C). This completes that proof that AS u (x : a1T2i ? A' u fx : al, which is the same as (AS1S2 u fx : a1J)T2 ? A' u fx : a). Because A' F e' : a and A' has satisfiable constraints, it is easy to see that the constraints of a are satisfiable with respect to A'. Hence by Lemma 3.18, A' u fx : a) has satisfiable constraints. Finally, AS1S2 u (x : a?) has acceptable inclusions. This allows us to apply the induction hypothesis a third time, showing that (S3,B2,r2) = Wos(A5152 u fx : ai),e") succeeds and that there exists T5 such that 1. T2 = S3T5, except on new variables of W08(AS?S2 U fx : a?),e11), 2. ASU (x : aiT2) H B2T5, and 3. AS u tx : aiT2) H T2T5 C T'. So (So,Bo,r0) = W08(A,let x = e'in e") succeeds with So = 515253, B0 = B1,53 u B2, and r0 = Let T be T5. Then 83 1. Observe that S0T