<<

F-Bounded Polymorphism for Object-Oriented Programming

Peter Canning, William Cook, Walter Hill, Walter Olthoff Hewlett-Packard Laboratories P.O. Box 10490, Palo Alto, CA 94303-0971 John C. Mitchell Department of Computer Science Stanford University, Stanford, CA 94309

Abstract ing was identified as an important form of polymor- phism in object-oriented programs. This lead to the Bounded quantification was introduced by Cardelli and development of “bounded quantification” in [7]. If we Wegner as a means of typing functions that operate uni- view objects as elements of non-recursive record types, formly over all subtypes of a given type. They defined then bounded quantification provides a useful form of a simple “object” model and used bounded quantifica- polymorphism over objects. However, a more sophis- tion to type-check functions that make sense on all ob- ticated presentation of object-oriented constructs (as jects having a specified of “attributes.” A more re- in [5, 11, 10]) would allow objects that are elements alistic presentation of object-oriented languages would of recursively-defined types. With recursive types, the allow objects that are elements of recursively-defined Cardelli-Wegner form of bounded quantification is not types. In this context, bounded quantification no longer sufficiently expressive to meet its original goal. serves its intended purpose. It is easy to find func- F-bounded quantification is a natural extension of tions that makes sense on all objects having a speci- bounded quantification that seems particularly useful fied set of methods, but which cannot be typed in the in connection with recursive types. The essential idea Cardelli-Wegner system. To provide a basis for typed may be illustrated by comparison with Cardelli-Wegner polymorphic functions in object-oriented languages, we bounded quantification. Using “⊆” for the subtype re- introduce F-bounded quantification. Some applications lation, a simple example of a bounded-quantified type of F-bounded quantification are presented and seman- is the type ∀t ⊆ τ. t → t. This is the type of func- tic issues are discussed. Although our original moti- tions which map t to t, for every subtype t of τ. In vation was to type polymorphic functions over objects, a setting where all structurally similar objects belong F-bounded quantification is a general form of polymor- to subtypes of a given type, many useful polymorphic phism that seems useful whenever recursive type defin- functions will have bounded quantified types. For ex- itions and are used. ample, if we type an object by listing its methods and their types, an object with a print method may have type {..., print: void → string,...}, indicating that the 1 Introduction method print produces a print representation of the object. In the view of subtyping presented in [8], Although object-oriented programming has attracted every type of this form will be a subtype of the type increasing interest in recent years, the development {print: void → string} of objects having only a print of polymorphic type systems for object-oriented lan- method. For example, guages has progressed slowly. One reason is that object- oriented languages are often described using terminol- {A: int → void, print: void → string} ogy that sets them apart from functional languages. In ⊆ {print: void → string}. addition, there has been a lack of formal models for object-oriented languages. As a result, it has been A function taking a list of printable objects, a string and difficult to see how practical polymorphic type sys- returning an object whose print representation matches tems should be adapted for typing object-oriented con- the given string will have the bounded-quantified type structs. In Cardelli’s seminal paper [8], record subtyp- ∀t ⊆ {print: string}. list[t] → string → t.

1 The flexibility of bounded quantification is dramati- may be imposed on the quantified type variable. Thus cally reduced when objects belong to recursively-defined Curtis’ system subsumes our more modest proposal. types. For example, consider the type However, we believe that our form of quantification is both sufficient to type-check practically useful object- PartialOrder = { lesseq: PartialOrder → Bool }. oriented programs, and more tractable. Some evidence for the naturality of F-bounded quantification is the Each object of this type has a method lesseq which may intriguing connection with F-coalgebras, the dual of a be applied to another object of the same type. We in- standard construction in the category-theoretic charac- tend the result of x.lesseq(y) to be true if x does not terization of type recursion [22]. exceed y in some ordering, and false otherwise. Using The next section surveys relevant background on lesseq, it should be possible to sort lists of PartialOrder strongly-typed object-oriented programming. Section 3 elements, for example. We may easily write a sort- illustrates in detail problems with previous techniques ing function with type ∀t ⊆ PartialOrder. list[t] → list[t]. for dealing with recursive object types. Section 4 intro- However, as we shall see later in the paper, object- duces F-bounded quantification and demonstrates that oriented versions of the usual partially-ordered types it solves the typing problems presented in the previous such as integers are not subtypes of PartialOrder. There- section. some speculative observations on the semantic fore, our generic sorting function cannot be used in the aspects of F-bounded quantification. Section 6 summa- way we might expect. To solve this problem and related rizes our contribution and indicates directions for future difficulties with other forms of recursive types we intro- research. duce a generalization of bounded quantification which we call F-bounded quantification, for want of better ter- minology. For the example at hand, consider the func- 2 Background tion F from types to types given by 2.1 Objects, Records and Recursive F[t] = { lesseq: t → bool }. Types We may write a polymorphic sorting function of type A fundamental premise underlying most models of ∀t ⊆ F[t].list[t] → list[t], where this function is defined on object-oriented programming is that objects may be re- any type t such that t ⊆ F[t]. Since integer ⊆ F[integer], garded as record whose components are functions rep- as explained in Section 3.3, we may apply such a sorting resenting methods [8, 7, 25, 11, 5]. In this model, “mes- function to lists of integers or lists of any other type of sage sending” is implemented by simple component se- objects having lesseq methods. lection. One practical application of F-bounded quantification Record types are used to describe the protocols [14] is for understanding some problems in the or interfaces of objects. A record type is a map- of the Eiffel [18]. Eiffel intro- ping of labels to types. A record consisting of labels duces a special type expression, like Current, to represent l1, . . . , lj with associated values in types σ1, . . . , σj has recursion at the type level. Like Current always repre- type {l1: σ1, . . . , lj: σj}. The fields of the record type sents the ‘current class’: in a class P it simply stands describe messages together with the types of their ar- for P , but when this class is inherited by a subclass C, guments and return values. This view is adopted in the like Current in an inherited attribute is reinterpreted to programming languages Amber [6], Modula-3 [10], and stand for the subclass C. The subclasses of such a class TS [17]. are usefully understood as having interfaces that sat- Even the very simplest “textbook” examples isfy an F-bound. However, as mentioned above, there from object-oriented programming produce recursively- is no necessary subtype relation among types satisfying defined record types [21, 1, 6, 16, 10]. For example, an F-bound. This analysis explains some insecurities in the type of a planar point with four methods is defined the Eiffel type-system, which always allows subclasses recursively as follows. to act as if they are subtypes of their parents. Further Point = { details are given in [12], along with some suggestions for x : void → Real, correcting Eiffel’s problems using the results in this pa- y : void → Real, per. The error in the Eiffel type system illustrates the move : Real × Real → Point, subtlety involved in designing flexible and sound type equal : Point → Boolean systems for object-oriented languages. } Another type system with a generalized form of bounded quantification is presented by Curtis [13]. In The body of the recursive type is a record type indi- this system, arbitrary collections of subtype constraints cated by braces {...}. The use of Point in the return

2 type of move indicates that the move method returns This means, informally, that if assuming s is a sub- an object that has the same type as the original point. type of t allows one to prove that σ is a subtype of τ, Its use as the argument type of equal indicates that the then the recursive type Rec s. σ is a subtype of Rec t. τ. equal method takes an argument with the same type. For example, the following type is a supertype of Point: In other words, equal is a ‘binary’ operation on points, viz. for two points p and q, the expression p.equal(q) is Movable = Rec mv. { move : Real × Real → mv } meaningful. because the body of Point is a subtype of the body of A useful notation for recursively defined types is the Movable, given the assumption pnt ⊆ mv: form Rec t.A . Intuitively, the type Rec t.A is the type t defined by t = A, where A generally contains the type pnt ⊆ mv ` {move: Real×Real → pnt,...} variable t. Using this notation, we may define Point as ⊆ {move: Real×Real → mv} follows. Rec pnt.{move: Real×Real → pnt,...} ⊆ Rec mv.{move: Real×Real → mv} Point = Rec pnt. { x : void → Real, 2.3 Bounded Quantification y : void → Real, move : Real × Real → pnt, Cardelli and Wegner’s language fun [7] uses bounded equal : pnt → Boolean quantification to type polymorphic functions over sim- } ple “objects” represented by records. Extensions to the language removed its reliance upon record field assign- Since the type variable pnt is bound by Rec, we may ment, so that record operations may be expressed func- rename pnt without changing the meaning of this dec- tionally [24, 15, 20]. The use of bounded quantification laration. may be illustrated with a simple type of cartesian point objects: 2.2 Record Subtyping SimplePoint = { x: int, y: int } Cardelli [8] identified record subtyping as an important form of polymorphism in object-oriented programming. Note that simple points do not have any methods which One basic axiom of record subtyping may be written in take simple points as arguments or return simple points the form as results. Consequently, the type SimplePoint does not require a recursive type declaration. {x1: σ1, . . . , xk: σk, . . . , x`: σ`} ⊆ {x1: σ1, . . . , xk: σk} A function that ‘moves’ simple points may be defined using bounded quantification. Move is a function of type The main idea is that if a record r has fields ∀t ⊆ SimplePoint. t → Real × Real → t and is x1: σ1, . . . , xk: σk and also xk+1: σk+1, . . . , x`: σ`, then defined by the expression following the equals sign. in particular r has fields x1: σ1, . . . , xk: σk. Therefore, any operation that makes sense on records of type move : ∀t ⊆ SimplePoint. t → Real × Real → t {x : σ , . . . , x : σ } also makes sense on records of type 1 1 k k = Fun[t ⊆ SimplePoint] fun(p:t) fun(dx,dy:Real) {x : σ , . . . , x : σ , . . . , x : σ }. A generalization of this 1 1 k k ` ` p with { x = p.x + dx, y = p.y + dy } axiom is the inference rule The notation Fun[t ⊆ SimplePoint] indicates that the σ1 ⊆ ρ1, . . . , σk ⊆ ρk, {x : σ , . . . , x : σ , . . . , x : σ } ⊆ {x : ρ , . . . , x : ρ } first argument of move is required to be a subtype of 1 1 k k ` ` 1 1 k k SimplePoint. The second argument must be a value in which takes into account subtyping within the fields. this subtype. Its third argument is a pair of numbers A standard rule is the function subtyping rule [19, 9]: representing the distance to be moved. The result of the function is computed by building a new record hav- σ0 ⊆ σ τ ⊆ τ 0 ing the fields in the original subtype value, but with σ → τ ⊆ σ0 → τ 0 updated x and y components. This new record has the same type as the original argument to move. 0 Noting that the hypothesis σ ⊆ σ is opposite to the Every subtype of SimplePoint is a legal argument to others, one says that the arrow constructor is con- move. For example, values of type SimpleColoredPoint, travariant in its first argument. One subtype rule for recursive types is the following [6]: SimpleColoredPoint = { x: int, y: int, color: int }

Γ, s ⊆ t ` σ ⊆ τ s free only in σ. are valid arguments to move, and the result of the ap- Γ ` Rec s. σ ⊆ Rec t. τ t free only in τ. plication is also a SimpleColoredPoint.

3 3 Recursive Types and Bounded translate : ∀r ⊆ Movable. r → Movable

Quantification which is no more general than the ordinary Movable → Movable. 3.1 Introduction The careful reader may notice that translate can in In this section we investigate the use of bounded quanti- fact be typed without using bounded quantification, giv- fication in polymorphic functions over objects with re- ing cursive types. We show that bounded quantification translate : ∀t. { move: Real × Real → t } → t does not provide the same degree of flexibility in the presence of recursion as it does for non-recursive types. However, this should not be regarded as a defect in our Two kinds of problems are identified, depending upon presentation; this works only because translate is an un- the location of the recursion variable within the recur- usually simple example. An essential aspect of translate sive type. In describing the two possibilities, it is useful is that the parameter x only occurs once in the body of to adopt the standard notion of “polarity” from logic. the function, where we access the move field. In a more In a type expression σ → τ, the subexpression τ oc- complicated function like curs positively and the subexpression σ negatively. If σ0 occurs with positive or negative polarity in σ, then this choose = fun(b:bool) fun(x:Movable) occurrence will have the opposite polarity in σ → τ. if b then x.move(1.0, 1.0) else x A subexpression of τ will have the same polarity in σ → τ. For example, t is positive in (t → σ) → τ in which the method is called and the object returned, but negative in t → (ρ → τ). Polarity is preserved the simple typing without bounded quantification is not in record type expressions, so that t is positive and s is possible. negative in {put: t → void, get: void → s}. 3.3 Subtyping and Negative Recursion 3.2 Subtyping and Positive Recursion For a recursive type with a negative recursion-variable, When the recursion variable of a recursive type appears the intuitive concept of ‘adding fields’ to produce sub- positively, subtyping does not ensure the intuitively ex- types does not work: the resulting types are not sub- pected typing behavior. Consider the recursive type types of the original recursive type. Consequently, Movable introduced above. The recursion variable mv bounded quantification cannot be used to quantify over in Movable only occurs positively. these types. To illustrate, assume we want to define a polymorphic minimum function on a PartialOrder type Movable = Rec mv. { move: Real × Real → mv } that describes values with a comparison method:

It is reasonable to define a function, translate, that PartialOrder = Rec po. { lesseq: po → bool } moves a movable value one unit in both directions: translate = fun(x:Movable) x.move(1.0, 1.0) minimum : ∀t ⊆ PartialOrder. t → t → t Although this function works for any value whose type The minimum function should return the lesser of its two is a subtype of Movable, the result of the function appli- arguments, determined by asking the first argument to cation is always of type Movable, according to the typing compare itself with the second. Intuitively, values of rules of [7]. It would be preferable to have a polymor- type Number or String should be admissible arguments phic translate which, for any subtype of t of Movable, for the polymorphic minimum, since they both have a takes argument of type t and return a value of the same lesseq operation as required. The type Number, in our type. However, an easy semantic argument shows that view of object-oriented languages, is a recursively de- translate as defined above does not have the type fined record type: translate : ∀r ⊆ Movable. r → r Number = Rec num. { . . . , lesseq: num → bool, . . . }

To see this, consider the type However, the polymorphic application minimum R = { move: Real × Real → Movable, other: A } [Number] is type-incorrect, because Number is not a sub- type of PartialOrder. If we try to derive Number ⊆ It is easy to see that R is a proper subtype of Movable. PartialOrder by unrolling the two types we obtain However, if we apply translate to an object of type R, we obtain an object of type Movable, not R. Thus the { . . . , lesseq: Number → bool,. . . } best we can say with bounded quantification is ⊆ { lesseq: PartialOrder → bool }

4 which requires PartialOrder ⊆ Number. This is con- In the this example we ‘work backwards’ to derive the trary to what we wanted to show, indicating that Num- F-bounded constraint from the typing problem posed by ber ⊆ PartialOrder is not derivable unless Number = translate. The problem is to derive a condition on a type PartialOrder. t so that for any variable x of type t, x.move(1.0, 1.0) has One type that is a subtype of PartialOrder is type t. In the following discussion we use the subtype rules of [9] or [19]. We are looking for the minimal Rec t. { . . . , lesseq: PartialOrder → bool, . . . } condition on t such that the following typing can be derived: An object of this type could be compared (using lesseq) with any other value of type PartialOrder, but since Par- x : t ` x.move(1.0, 1.0) : t tialOrder does not provide any fields on which to base this comparison, objects of this type have little practi- By the application (APP) and selection (SEL) rules, cal value. In situations where more fields are present this reduces to such types may be useful, but the problem remains that subtyping cannot capture the intuitive polymorphism x : t ` x : { move : Real × Real → t } desired for minimum. Using the subtyping rule we then derive 4 F-bounded Quantification τ ⊆ {move: Real× Real → t} x: t ` x: τ

4.1 Introduction Since the type τ does not occur in any other assumption, F-bounded quantification allows the practical examples we may simplify to the requirement given above to be type-checked with intuitively desirable types. We say that a universally quantified type is F- t ⊆ { move : Real × Real → t }, bounded if it has the form which cannot be proved without additional assump- ∀t ⊆ F [t].σ tions. Expressing this condition as t ⊆ F-Movable[t], where where F [t] is an expression, generally containing the type variable t. The semantics of F-bounded quantifi- F-Movable[t] = { move : Real × Real → t } cation are discussed briefly in Section 5. it is clear that this condition fits the format of F- F-bounded polymorphic types differ from ordinary bounded quantification. Motivated by the preceding bounded types by binding the type variable in both discussion, we define the F-bounded polymorphic func- the result-type σ and the type bound F [t]. If F [t] is tion: a type of the form F [t] = {ai: σi[t]}, then the con- dition A ⊆ F [A] says, in effect, that A must have translate = Fun[ t ⊆ F-Movable[t] ] the methods a and these methods must have ar- i fun(x:t) x.move(1.0, 1.0) guments as specified by σi[A], which are defined in terms of A. Thus A will often be a recursive type, with F-bounded polymorphic type suggesting that F-bounded quantification is closely related to type recursion. But bounded quantifi- translate : ∀t ⊆ F-Movable[t] . t → t cation ∀t ⊆ (Rec r.F [r]).σ(t) over a recursive type is very different from the F-bounded quantification Since Point ⊆ F-Movable[Point], the application trans- ∀t ⊆ F [t].σ(t) over the type-function F that defines late[Point] is type-correct, and has result of type Point the recursive type, as shown in the following sections. → Point. Of course translate will also work for other types that satisfy the constraint t ⊆ F-Movable[t], 4.2 Positive Recursion such as ColoredPoint, defined as follows. As we saw in Section 3.2, the polymorphic application ColoredPoint = Rec pnt. { translate[Point] produces a function of type Point → x : void → Real, Movable, rather than Point → Point as desired. A y : void → Real, simple type derivation will both motivate the definition c : void → Color, of F-bounded quantification, and show how it can be move : Real × Real → pnt, used to achieve the desired typing of translate. }

5 It is interesting to note that the type function F- following statement is technically imprecise, it seems in- Movable is related to the recursive type tuitively helpful to say that F-bounded quantification characterizes the types that have “recursive structure” Movable = Rec mv. { move: Real × Real → mv } similar to the type Rec t. F [t]. Intuitively, a type F [A] describes a set of meaningful operations, possibly ac- that failed to provide the desired typing in Section 3.3. cepting values of type A as arguments or returning such F-Movable is constructed syntactically by regarding the values as results. Elements of type A have these oper- body of the recursive type expression as a type function. ations if we may view each element of A as an element of F [A], i.e., A ⊆ F [A]. 4.3 Negative Recursion One type that always satisfies A ⊆ F [A] is the re- cursive type A = Rec t. F [t]. More generally, if G[t] is In Section 3.3, we saw that Number is not a subtype of a type expression and G[t] ⊆ F [t] for all t, then the PartialOrder. Nevertheless, the types Number and String, recursive type A = Rec t. G[t] also satisfies A ⊆ F [A]. as well as the type PartialOrder all have binary opera- This follows from the observation that if G[t] ⊆ F [t] tions lesseq. As a consequence, the expression x.lesseq(y) for all t, then A = G[A] ⊆ F [A]. However, it is worth is well-typed if x and y both have one of these types, but noting that (depending on F ) there may be other types not if x and y have different types. However, using ordi- satisfying t ⊆ F [t] which do not have this form. nary bounded quantification, it does not seem possible to define a polymorphic minimum function that works correctly for the types PartialOrder, Number or String. 5 Semantics In this section, we will see that F-bounded quantifica- tion allows us to define such a polymorphic minimum There several ways of developing semantics for F- function. This is an important advance, since current bounded quantification. We have not explored any of typed object-oriented languages are notoriously restric- these in detail. Here we will simply sketch some ap- tive when it comes to binary operations. proaches to semantics and an intriguing connection to The common structure among PartialOrder, Number F-algebras. and String may be described using a type function de- For a direct semantics, it is useful to have a way to rived from the recursive definition of PartialOrder: denote the family of all types that satisfy the bound t ⊆ F [t] for each F . This collection of types would F-PartialOrder[t] = { lesseq: t → bool }. constitute a , in the sense of [4, 3], analogous to the POWER kind of [9]. This may be achieved by defining Applying F-PartialOrder to Number we see that a kind constructor FBOUND : (TYPE → TYPE) → KIND with intuitive interpretation F-PartialOrder[Number] = { lesseq: Number → bool } FBOUND[F ] = {t | t ⊆ F [t]} and hence Given this constructor, the type ∀t ⊆ F [t].σ Number ⊆ F-PartialOrder[Number] may be interpreted using kinded quantification as ∀t: FBOUND[F ].σ. We see no problem in incorporat- Although Number is not a subtype of PartialOrder, it is a ing this into the model definition of [3]. Another view subtype of F-PartialOrder[Number], which is all we need may be derived from constrained quantification of Cur- to compute minimum. Forming the F-bounded polymor- tis [13], since F-bounded quantification is subsumed by phic function his system. minimum = Fun[t ⊆ F-PartialOrder[t]] An alternative approach is to use the semantics- fun(x:t) fun(y:t) if x.lesseq(y) then x else y by-translation of Breazu-Tannen et.al. [2]. In their semantics, bounded type-derivations in the language with type with bounded quantification are translated into type- derivations in a simpler calculus with explicit coer- minimum : ∀t ⊆ F-PartialOrder[t] . t → t → t cions. In particular, the type ∀t ⊆ τ. σ is translated to ∀t. (t → τ) → σ, in which t → τ is the explicit we capture a form of polymorphism which does not seem coercion. Since τ is in the scope of the universal quanti- possible with ordinary bounded quantification. fication of t, there is no problem with allowing τ to have Although we have discussed negative and positive re- the form F [t] in the translated language. One techni- cursion separately, F-bounded quantification also works cal point in [2] is a coherence condition requiring, intu- when both occur in the same recursive type. While the itively, that any two type-derivations for an F-bounded

6 term must translate into provably equivalent terms in meaningful use of object with this type. Hence F- the calculus with explicit coercions. Coherence is a dif- bounded quantification seems to be “exactly what we ficult technical property, and we have not verified it for need” in order to type polymorphic functions over ob- our calculus. jects with recursive types. Regardless of how we interpret a subtyping assertion A ⊆ B, it is clear that this assertion implies some kind of map from A to B. This simple observation leads 6 Conclusion us to some interesting connections between F-bounded quantification and the standard category-theoretic ma- We have identified a generalization of bounded quanti- chinery associated with recursive type definitions [22]. fication, called F-bounded quantification, in which the To begin with, in most semantics of recursive types, bound type variable may occur within the bound. We it is possible to extend type functions defined by type argue that F-bounded quantification is useful for typing expressions to functors (maps on types and functions) programs involving recursive types: it allows quantifi- over some category (perhaps with a more limited choice cation over types that are “structurally similar” to the of functions than we actually define in programming). recursive type Rec t. F [t]. If we have a functor F and wish to find a type t sat- As directions for future work, we note that F-bounded isfying t = F [t], where = means isomorphism, then it quantification is closely related to inclusion for single- suffices to find an initial F-algebra, where an F-algebra sorted algebraic signatures. F-bounded quantification is a pair ht, fi with f: F [t] → t. It is an easy exercise to captures the notion of adding more operations to a re- prove that if ht, fi is an initial F-algebra, then f has a cursive type while preserving the recursive structure of two-sided inverse f −1. The dual of an F-algebra is an the type. F-coalgebra, which is a pair ht, fi with f: t → F [t]. The F-bounded quantification also has an impact on the argument showing that an initial F-algebra is a solution relation between inheritance and subtyping in object- to t = F [t] also shows that the final F-coalgebra satisfies oriented programs. As noted in Section 4.3, two types t = F [t]. t1 and t2 may satisfy an F-bound (t1 ⊆ F [t1] and In F-bounded polymorphism, we quantify over all t2 ⊆ F [t2]) but not be in a subtype relation (neither types t with t ⊆ F [t]. Taking into account that t ⊆ F [t] t1 ⊆ t2 or t2 ⊆ t1). This means that a F-bounded implies some kind of map from t to F [t], this means function may be applied to (or “inherited” by) objects we are essentially quantifying over pairs ht, fi with with incomparable types, demonstrating that the inher- f: t → F [t], or some family of F-coalgebras. (The itance is distinct from the subtype hierarchy quantification over some family of maps t → F [t] is [23]. In the Abel project at HP Labs, we are explor- made explicit in the translation in [2].) Since the recur- ing the consequences of this separation on programming sive type Rec t. F [t] may be regarded as a particular F- language design. coalgebra, this suggests that F-bounded polymorphism involves quantification over a category whose objects are properly regarded as “generalizations” of the recursive References type Rec t. F [t]. [1] Alan H. Borning and D. H. H. Ingalls. Multiple One way of seeing why this provides useful poly- inheritance in smalltalk-80. pages 234–237, 1982. morphism in object-oriented languages is to consider the typing rules associated with recursive types. If [2] Val Breazu-Tannen, Thierry Coquand, Carl A. t = Rec t. F [t], then we have an “introduction” rule Gunter, and Andre Scedrov. Inheritance as implicit saying that if an expression e: F [t] then e: t. The “elimi- coercion. Inf. Comput., 93(1):172–221, 1991. nation” rule gives the converse: if e: t then e: F [t]. These rules are based on the two directions of the isomor- [3] K. B. Bruce, A. R. Meyer, and J. C. Michell. The phism t = F [t]. If A satisfies the F-bounded condition semantics of second-order . Infor- A ⊆ F [A], then A is a type which has the “elimination” mation and Control, 1986. typing rule associated with Rec t. F [t], but not neces- sarily the associated “introduction” rule. This is a pre- [4] Kim B. Bruce and Giuseppe Longo. A mod- cise way of saying that at type A satisfying A ⊆ F [A] est model of records, inheritance, and unbounded shares “structural similarity” with the recursive type quantification. Inf. Comput., 87(1-2):196–240, Rec t. F [t]. In general, for recursive types of the form 1990. [5] Peter Canning, William Cook, Walt Hill, John Rec t.{method1: σ1,..., methodk: σk} Mitchell, and Walter Olthoff. F-bounded polymor- it seems that only the “elimination” is needed to make phism for object-oriented programming. In Proc. of

7 Conf. on Languages and [18] Bertrand Meyer. Object-oriented Software Con- Computer Architecture, pages 273–280, 1989. struction. International Series in Computer Sci- ence. Prentice Hall, 1988. [6] L. Cardelli. Amber. In Combinators and Func- tional Programming Languages, volume 242 of Lec- [19] John C. Mitchell. Type inference and type contain- ture Notes in Computer Science, 1986. ment. In Semantics of Data Types, volume 173 of Lecture Notes in Computer Science, pages 257–278. [7] L. Cardelli and P. Wegner. On understanding Springer-Verlag, 1984. types, data abstraction, and polymorphism. Com- puting Surveys, 17(4):471–522, 1986. [20] Dedier R´emy. Typechecking records and variants in a natural extension of ML. In Proc. of the ACM [8] . A semantics of multiple inheritance. Symp. on Principles of Programming Languages, In Semantics of Data Types, volume 173 of Lecture pages 77–88, 1989. Notes in Computer Science, pages 51–68. Springer- Verlag, 1984. [21] J. C. Reynolds. User-defined types and procedural data structures as complementary approaches to [9] Luca Cardelli. Structural subtyping and the no- data abstraction. In New Advances in Algorith- tion of power type. In Proc. of the ACM Symp. on mic Languages, pages 157–168. Inst. de Recherche Principles of Programming Languages, pages 70– d’Informatique et d’Automatique, 1975. 79. ACM, 1988. [22] Michael B. Smyth and Gordon D. Plotkin. The [10] Luca Cardelli, James Donahue, Lucille Glass- category-theoretic solution of recursive domain man, Mick Jordan, Bill Kalsow, and Greg Nelson. equations. SIAM J. Comput., 11(4):761–783, 1982. Modula-3 report (revised). Technical Report 52, [23] A. Snyder. CommonObjects: An overview. SIG- Digital Equipment Corporation Systems Research Plan Notices, 21(10):19–28, 1986. Center, December 1989. [24] Mitchell Wand. Complete type inference for simple [11] William Cook. A Denotational Semantics of Inher- objects. In Proc. IEEE Symposium on Logic in itance. PhD thesis, Brown University, 1989. Computer Science, pages 37–44, 1987. [12] William Cook. A proposal for making Eiffel type- [25] Mitchell Wand. Type inference for record concate- safe. In Proc. European Conf. on Object-Oriented nation and multiple inheritance. In Proc. IEEE Programming, pages 57–70. British Computing So- Symposium on Logic in Computer Science, pages ciety Workshop Series, 1989. Also in The Computer 92–97, 1989. Journal, 32(4):305–311, 1989.

[13] Pavel Curtis. Constrained qualification in polymor- phic type analysis. PhD thesis, Ithaca, NY, USA, 1990.

[14] A. Goldberg and D. Robson. Smalltalk-80: the Language and Its Implementation. Addison- Wesley, 1983.

[15] L. Jategaonkar and John C. Mitchell. ML with ex- tended pattern matching and subtypes. In Proc. of the ACM Conf. on Lisp and Functional Program- ming, 1988.

[16] Ralph Johnson and Justin Graver. A user’s guide to Typed Smalltalk. Technical Report UIUCDCS- R-88-1457, University of Illinois, 1988.

[17] Ralph Johnson, Justin Graver, and L. Zurawski. TS: An optimizing compiler for Smalltalk. In Proc. of ACM Conf. on Object-Oriented Programming, Systems, Languages and Applications, 1988.

8