Module Constructs for Object-Oriented and Functional Programming ...

1 downloads 71 Views 207KB Size Report
Jan 1, 1993 - We propose to design module constructs incorporating the best ... emphasis in the object-oriented programming language community has been.
Module Constructs for Object-Oriented and Functional Programming Languages Dissertation Proposal Gerald Baumgartner Department of Computer Sciences Purdue University West Lafayette, IN 47907 [email protected] January 1, 1993

Abstract

Object-oriented languages o er mechanisms to help structure large programs. However, the semantics of these constructs are often not very precisely de ned. For example, the use of inheritance as a substitute for subtype polymorphism in many object-oriented languages either leads to an unsound or a too in exible type system. In addition, ideas from module constructs of functional languages could increase the expressiveness of object-oriented languages and vice versa. We propose to design module constructs incorporating the best features found among module constructs of object-oriented languages and of functional languages. In particular, we plan to incorporate parametric polymorphism, subtype polymorphism, overloading, type abstraction, and compile-time type inference in a semantically clean manner. We try to achieve this with a minimumamount of declarations required from the programmer and a minimum amount of run-time type information.

1 Introduction Module constructs are generally considered an important tool for helping structure large programs. Most modern programming languages, therefore, provide some kind of module constructs. 1

Smalltalk-80 [15] popularized a module concept that treats data as life entities, called objects, that are communicating by sending messages. This design proved very useful and intuitive for organizing large programs. Since then many other languages have been designed using similar module constructs; such languages are called object-oriented languages. The main disadvantage of Smalltalk-80 is that it is an untyped language, and, therefore, many programming errors cannot be detected until run time. Other object-oriented languages have been designed by incorporating the module constructs with the type system, but their module system is either less expressive, such as in C++ [14], or their type system is unsound, such as in Eiffel [24]. On the other hand, in the functional programming language community, modules with di erent characteristics were developed, for example, ML's module system [21] with its parametric polymorphism. Traditionally, the emphasis in the object-oriented programming language community has been on ecient implementation, while the emphasis in the functional language community has been on a semantically clean design and on type inference. To build a more exible module system it seems desirable to combine the features of modules found in object-oriented languages and of those found in functional languages. Such a language would be strongly typed with a type system containing parametric polymorphism, subtype polymorphism, overloading, and type abstraction, and its compiler would infer the types of all variables. Unfortunately, such a language cannot exist since type inference would become undecidable. And without type inference, type expressions in such a language become so complicated that it is too much of a burden for programmers to specify types in declarations. In order to combine the module constructs of those two di erent worlds, it is necessary to nd a compromise between requiring all variables to be declared and full type inference on the one hand and a compromise between highly expressive module constructs and an ecient implementation on the other hand. By asking programmers to provide a modest amount of declarations in strategic places and by having some limited type information available at run time it should be possible to combine the best features of object-oriented and functional module constructs. Preliminary results in extending C++ modules [4] suggest that this can be done. Following we present motivation from our paper [4] why the module system should be incorporated with the type system while keeping subtyping and inheritance separated. We also use our example from [6] to demonstrate the need for exibility in structuring programs that goes beyond the capa-

2

bilities of many object-oriented languages. Another example demonstrating the limitations of object-oriented languages can be found in [16] and in [4]. In the next two sections we review and de ne some terminology and then discuss module constructs found in several existing languages. Following that we outline our ideas for designing and implementing module constructs.

1.1 Incorporating Types and Modules

Mathematically speaking, a type is a set of values. In most traditional programming languages such a set is characterized implicitly by providing an implementation for the type, e.g., using a primitive type the hardware provides. However, there is another way to characterize a type: by specifying base elements, operations on the type, and axioms limiting the behavior of those operations. For example, a stack can be speci ed by emptystack as a base element, the operations push, pop, and top, and the axioms pop pop top top

(emptystack) = error (push (elem, stack)) = stack (emptystack) = error (push (elem, stack)) = elem

A type speci ed thus is called an abstract type. It is desirable to provide language support for specifying abstract types so that the compiler can print error messages for incorrect use of the operations of the abstract type. Typed object-oriented languages allow us to de ne a type similarly by declaring a class. However, a class is also used to specify the implementation of the type. In addition, class inheritance is often used for purposes of both reusing the implementation of the superclass and subtyping. Since inheritance and subtyping are semantically di erent [12], this either weakens the expressiveness of the language or leads to type insecurities. An example from [30] illustrates this point. Consider two abstract types stack and dequeue (doubly ended queue). The abstract type dequeue provides the same operations as stack and in addition two operations for pushing and popping elements at the bottom of the stack. Therefore, dequeue is a subtype of stack. The easiest way to implement dequeue and stack is to structure the inheritance hierarchy opposite to the type hierarchy. A doubly ended queue is implemented naturally as a doubly linked list. A stack implementation could then just copy the doubly ended queue implementation and remove the additional operations. 3

In order for the type system to be sound it is not possible to use inheritance for subtyping purposes and also allow the removal of operations [12]. Most programming languages choose therefore to restrict the power of inheritance.

1.2 Computer Algebra

Using an example from computer algebra [6], we demonstrate that a complex type hierarchy cannot be modeled by a class hierarchy. In computer algebra, the distinction between abstract types and concrete types arises naturally. Typical abstract types are group, ring, field, or euclidean-domain, while typical concrete types are integer, fraction, or distributed-polynomial. To maintain these di erences, abstract and concrete types should not be pressed into the same class hierarchy of an object-oriented language. Consider, for example, the abstract types general-matrix and positive-definite-matrix. The di erence between them is that for positive de nite matrices we have additional functions, like inverse(), which we do not have for general matrices. Everything that is provided for general matrices, however, could be inherited by the abstract type for positive de nite matrices. On the other hand we might have several di erent implementations of matrices, like two-dimensional arrays (dense-matrix), lists of triples (sparse-matrix), or matrices in band-matrix form. Pressing these implementations into the same hierarchy as the abstract types requires duplication of code to use the appropriate implementation for both general matrices and positive de nite matrices. Similar arguments have been given in the literature that the collection class hierarchy of Smalltalk-80 [15] is not appropriate as a basis for subtyping. While the problem does not arise with dynamic typing, it becomes an issue when trying to make Smalltalk-80 statically typed while retaining most of its exibility. The solution is to factor out the implementation aspects of classes into prototypical objects [19] or to factor out the type aspects into interfaces [8, 11].

2 Terminology Di erent programming languages use di erent semantics of their module constructs. In order to compare programming languages we need to introduce some terminology to capture the essentials of object-oriented module constructs. 4

Object An object is a data structure (usually implemented as a record)

having state variables, called elds, and functions, called methods, that work on the data structure. Class A class speci es the structure of objects and provides implementations for methods. Objects are created by instantiating the class. A class de nes a type of objects (see below). Inheritance Inheritance is a means to de ne a class by specifying the difference to a previously de ned class. The class being inherited from is called superclass, the inheriting class is called subclass. Inheritance from one superclass is called single inheritance, inheritance from more than one superclass is called multiple inheritance. Most languages restrict inheritance by requiring that the subclass is an extension of the superclass, i.e., the subclass can copy the de nition of the superclass and add new elds and new methods, but it cannot remove elds or methods of the superclass. These three concepts are generally considered the main ingredients of object-oriented languages. For example, Wegner [35] de nes object-oriented = objects + classes + inheritance Objects and classes allow a programming style in which code is organized by data type instead of by functionality, which is helpful in structuring big programs. The use of inheritance allows reuse of existing code. The de nition of type in a programming language is crucial as it in uences the design of the module constructs. For comparing di erent type systems we use the following de nitions. Type We de ne a type simply to be a set of values. For example, the type integer is the set of all integers. A class type is the set of objects that are instances of the same class. Concrete type A concrete type is a type whose elements have a common data representation. Examples of concrete types are integers or class types. Abstract type An abstract type or abstract data type is a type whose objects have a common set of public methods which observe a set of axioms. I.e., an abstract type constists of objects with common 5

behavior. The objects of an abstract type do not need to have a common data representation or a common implementation of public methods. We call a syntactic de nition of an abstract type a signature. Since dealing with axioms can be impractical in a programming language, they are often left out and replaced by property names or only by comments.

3 Modules in Existing Languages In this section we give a short overview of the di erent language constructs and mechanisms provided in a range of object-oriented and functional programming languages.

3.1

C++ C++ [14] is probably the most widely used object-oriented language today. It provides classes with multiple inheritance and data abstraction using public, private, and subtype-visible (protected) declarations. Classes can be parameterized with type parameters. The inheritance hierarchy is used for subtyping purposes. C++ is strongly typed and supports virtual methods. Except for the tables for virtual method lookup no run-time type information is needed. In addition, C++ allows the programmer to overload functions and to de ne coercions that are automatically applied by the compiler if needed.

3.2

Russel According to our de nition, Russel [13] is not an object-oriented language, but it has an interesting and radical type system. Russel does not have concrete types, only abstract types are provided. Russel de nes a type to be a set of functions. Type information is used to interpret values drawn from un untyped universe. Types themselves are values from this universe, which implies that types can be passed to functions and returned from functions. Russel does not have parameterized types, but uses the ability of functions to return types to achieve the same e ect. No data abstraction is available as a consequence of using values from an untyped universe, but Russel o ers implementation independence which is a notion similar to our notion of type abstraction.

6

By introducing some syntactic constraints it is assured that Russel programs can be fully type-checked at compile type.

3.3

Trellis/Owl Trellis/Owl [29] is an object-oriented language with multiple inheritance. Data abstraction is achieved by providing public, private, and subtypevisible declarations. Classes have two parts, a speci cation part and an implementation part. Only the speci cation part, i.e., only the function signatures of public methods are inherited. Classes can be parameterized with a type parameter, and subtyping is provided. The language provides both instance elds and type elds that are shared by all instances. Similarly, methods can be declared to work on an instance or on the type as a whole; virtual methods are supported. Objects need to be passed explicitly as the rst argument of methods. Full type checking is done at compile time, but type information is also available at run time.

3.4

Emerald Emerald [7] provides objects and abstract types with multiple inheritance. It does not provide classes, but since it has rst class types, it is possible to write objects that create other objects. These object-creators take on the r^ole of classes. Emerald is strongly typed and provides subtyping. Abstract types can have multiple implementations; there is no facility for data abstraction. The main innovation of Emerald is that objects can be moved between machines. To help achieve that full run-time type information is provided.

3.5

Scratchpad II Scratchpad [32, 34], a language designed for computer algebra, allows to write parameterized classes and provides a construct similar to parameterized signatures called category. Semantically, however, a category is not an abstract type containing objects but a higher-order type containing class types. In addition, the language allows to specify subtypes by specifying a supertype and a boolean expression that distinguishes the elements of the subtype from those of the supertype. Scratchpad allows method declarations in categories to have default implementations. Besides method declarations, categories can also contain properties of the type, such as whether a method is associative or re exive.

7

Some of these property names are prede ned and are used by the compiler for optimization purposes. Properties can also be used to export methods conditionally. Virtual methods are not supported. Unlike most object-oriented languages, method dispatch is not only performed based on the rst argument of a method but based on all arguments and on the return type. Scratchpad is strongly typed, but it requires full run-time type information for method dispatch.

3.6

Eiffel Eiffel [24] is a small typed object-oriented language with multiple inheritance. The inheritance hierarchy is used for subtyping purposes; since Eiffel allows to rename methods when inheriting them, subtyping is unsound. A noteworthy feature of Eiffel is that the programmer can specify preconditions and postconditions of methods and class invariants.

3.7

Modula-3 Modula-3 [9] is an object-oriented systems programming language with single inheritance. Instead of de ning a method inside a class, methods are only declared in a class and initialized with a top-level function constant. Virtual methods are not supported. The language o ers structural type equivalence, including structural type equivalence of in nite expansions of recursive types [1, 2], and subtyping with prede ned subtype relationships for built-in types. Subtyping is independent of the inheritance hierarchy. Separate from classes, Modula-3 o ers module constructs that allow, according to our terminology, the de nition of objects. These modules cannot be instantiated and don't have inheritance. However, they can be parameterized and allow the separation of interface and implementation. The latter corresponds to our notion of type abstraction if modules are considered types with one element. Modula-3 provides opaque types, i.e., types with hidden components, as a means of data abstraction.

3.8

POOL-I POOL-I [3] is a strongly typed object-oriented language with parameterized classes, parameterized signatures, multiple inheritance, and subtyping decoupled from inheritance. In addition to methods and elds, objects can

8

contain a process which is executed in parallel with the processes of other objects. Processes are not inherited. No construct for data abstraction is provided, and virtual functions are not supported. Signatures can contain property names. For a class to conform to a signature, the class needs to de ne the same property names. POOL-I o ers constructs to automatically create get-value and/or put-value methods for elds declared in a class.

3.9

ML ML [25, 26] is an eager functional language with an elaborate module system [21, 22] based on the dependent types of Martin Lof's intuitionistic type theory [23]. The ML core language, i.e., ML without modules, o ers a restricted form of parametric polymorphism. The restriction is that polymorphic functions cannot be used as arguments to functions. ML compilers infer the types of all variables except in cases involving overloaded built-in functions such as `+.' At run-time, no type information is available. The ML module system consists of constructs similar to implementation modules and de nition modules in Modula-2 [36]. In addition, ML supports a form of function, called functor, that takes implementation modules as arguments and returns them as result. The e ect of using functors is similar to using parameterized modules. Both functors and datatype declarations in the core language can be used to achieve data abstraction. Structures are not classes since they cannot be instantiated. At run-time, structures are represented as records, functors are represented as functions, and signatures don't have any representation. In fact this translation is performed in the front end of the compiler; the backend does not know anything about modules. Several attempts have been made to make ML more expressive by including subtyping. Most of these attempts concentrate on introducing subtyping into the ML core language by providing extendable record types similar to classes with inheritance, and on extending type inference to handle extendable record types. See, for example, the papers by Remy [28], Stansifer [31], and Wand [33]. Mitchell, Meldal, and Madhav [27] propose to extend ML modules with subtyping and inheritance. This extension would make ML an objectoriented language with a exible form of multiple inheritance, parameterized signatures containing function signatures and axioms, functors, rst-class

9

classes, and subtyping. However, it has not been shown yet how to extend type inference to these module constructs, and no implementation exists so far. The provision for rst-class classes will make a run-time representation of types necessary.

3.10

Haskell Haskell [17, 18] is a lazy, purely functional language based on a similar type system as ML. Like ML, it supports parametric polymorphism and its compiler infers types of expressions. As a purely function language, Haskell doesn't have assignment and, therefore, it cannot have objects with, according to our de nition, require state. However, it o ers type classes, which are similar to Scratchpad's categories. Syntactically, a type class consists of a list of function signatures. Semantically, a type class is the type of types. That is, both user-de ned types and built-in types are instances of type classes. In addition, Haskell provides overloading. In [20], Laufer presents an extension of both Haskell and ML with rstclass abstract types by extending the type system with existential types.

4 Design of New Module Constructs All of the module concepts listed above lack some features. None of the object-oriented languages has parametric polymorphism. Most languages either don't have subtyping or use inheritance as a substitute for subtyping. And few languages o er a clean separation between speci cation of abstract data types (signatures) and their implementations (classes). The only module concept having all those features is the extension of ML proposed by Mitchel et al. But this proposal is overly complex because of trying to acomodate di erent styles of programming, namely functional and object-oriented styles, and by designing the language as a speci cation and prototyping language (e.g., the use of axioms). Furthermore, making classes rst-class objects requires a higher amount of run-time type information and makes the type system more complex since other types are not mentioned to be rst-class. Based on our experience of adding a signature construct to C++ [4, 16] and separating subtyping from inheritance, we believe that it is possible to design module constructs to o er the best features from both the functional world and the object-oriented world. The features we are interested in are 10

a separation of speci cation and implementation (i.e., signatures and classes),  parameterization of signatures and classes,  a separation of subtype polymorphism and inheritance,  parametric polymorphism and a controlled form of overloading,  and type inference. The key to designing module constructs is to choose a proper de nition of type. Ideas for a type system can be found in intuitionistic type theory, denotational semantics, category theory, and in algebraic speci cation. We propose to design our module constructs as an extension of ML, since the formal de nition of ML [25, 26] provides us with a formal framework that gives guidance in designing the type system. Once the design has been tested in ML's formal framework, we propose to incorporate the ideas into our extension of the C++ module system. 

5 Implementation As Russel demonstrates, very powerful module constructs can be designed by making types rst-class values. The disadvantage of such a solution is that it becomes less ecient since a large amount of type information needs to be available at run-time. We plan to design the type system so that a minimal amount of run-time type information is needed. For example, for adding signature support to C++ it is possible to represent the interface between each signature-class pair essentially with only one vector of function addresses, called a signature table. Objects as elements of an abstract type are then accessed with a signature pointer containing a pointer to the object itself and a pointer to the signature table1 . For details and for design alternatives see [4]. We propose to implement our module constructs in a preprocessor to ML. Eventually, the ideas developed for ML should be incorporated into C++ and implemented in the GNU GCC compiler, but this would be beyond the scope of the thesis. 1 Actually, in our implementation a signature pointer also contains a pointer to the objects virtual function table because of the way objects are implemented in GCC. See the release information for our implementation [5] for an explanation of the di erences between the description in [4] and the implementation.

11

6 Conclusions We proposed the design of module constructs that combine the best features of the module constructs found in functional languages and object-oriented languages. This research should prove interesting to the object-oriented language community, because it applies theoretical results developed for functional languages to the design of an object-oriented language. It should also be of interest to the functional language community by providing an ecient way for adding subtype polymorphism to a functional language.

A More Terminology In this appendix, we list some additional terms that have been used in the comparison of languages above: Virtual method A virtual method is a method that can be overwritten in a subclass or for which the superclass relies on the subclass to implement it. Data abstraction Data abstraction refers to hiding some or all of the elds and some of the methods of an object. Two popular methods of implementing data abstraction are the use of opaque types, where the details are only visible in the implementation part of a module, and the use of private and public scopes in the de nition of a module. Type abstraction Type abstraction refers to hiding the entire implementation of concrete types only retaining the abstract type information. Function signature The signature of a function consists of the function name, the return type, the argument types, and, possibly, the list of exceptions that can be raised by the function. Class signature The signature of a class is the list of function signatures of the class's public methods together with public type declarations. The signature of a class de nes an abstract type, which is the type abstraction of the type de ned by the class. We use the term signature as an abbreviation of \the class signature of some class." 12

Module We use the term module to stand for any language construct that

groups data structures and/or functions. A class is an example of a module. Subtype A type S is said to be a subtype of a type T if S is a subset of T . If S and T are abstract types, then S is a subtype of T if and only if every function signature in the signature de ning T also occurs in the signature de ning S . Static typing A language is said to be statically typed, if the concrete type of every expression can be determined at compile time. Strong typing A language is said to be strongly typed, if its compiler can guarantee that a program it accepts will execute without type errors. If a language is statically typed, then it is also strongly typed; the converse is not necessarily true. Type inference Type inferences refers to deducing the type of variables which have not been declared from the context. The following terminology refers to ways to achieve strong typing without limiting ourselves to static typing. The de nitions are similar to the ones found in Cardelli and Wegner [10]: Polymorphism A language is said to be polymorphic if some values and variables may have more than one concrete type. A polymorphic function is a function whose arguments can have more than one concrete type. Parametric polymorphism Parametric polymorphism is achieved when a function works uniformly over a potentially in nite range of argument types. Subtype polymorphism Subtype polymorphism is achieved when the different types a value or variable can have are limited to be subtypes of some given type. Subtype polymorphism is also referred to as inclusion polymorphism. Overloading Overloading is a form of polymorphism, where a function name refers to di erent, unrelated functions depending on context. 13

Coercion Coercion is a form of polymorphism, where function arguments

or right hand sides of assignments are implicitly coerced to the type expected by the function or the the type of the variable being assigned to. Universal polymorphism Universal polymorphism refers to either parametric polymorphism or subtype polymorphism. Ad-hoc polymorphism Ad-hoc polymorphism refers to either overloading or coercion. According to Martin Lof's intuitionistic type theory [23], types can be represented by arbitrary propositions, using primitive types such as integer as atoms together with type constructors, the logical connectors ^, _, !, and bounded and unbounded universal and existential quanti cation. For analyzing object-oriented language constructs, we are particularly interested in quanti ed types. As explained by Cardelli and Wegner, quanti ed types correspond to programming language concepts as follows. Universal types are types achieved by parametric polymorphism. Bounded universal types are types achieved by universal polymorphism. Existential types are abstract types. Bounded existential types are types achieved by abstract subtyping.

14

References [1] Roberto M. Amadio and Luca Cardelli. Subtyping Recursive Types. DEC SRC Report 62, Systems Research Center, Digital Equipment Corporation, Palo Alto, California, November 1990. [2] Roberto M. Amadio and Luca Cardelli. \Subtyping Recursive Types." In Conference Record of the 18th Annual ACM Symposium on Principles of Programming Languages, Orlando, Florida, 21{23 January 1991, pp. 104{118. [3] Pierre America and Frank van der Linden. \A parallel object-oriented language with inheritance and subtyping." In Proceedings of the OOPSLA '90 Conference on Object-Oriented Programming Systems, Languages, and Applications, Ottawa, Canada, 21{25 October 1990. SIGPLAN Notices, Vol. 25, No. 10, October 1990, pp. 161{168. [4] Gerald Baumgartner and Vincent F. Russo. \Type abstraction and subtype polymorphism for object-oriented languages." Submitted to the ACM SIGPLAN '93 Conference on Programming Language Design and Implementation, Albuquerque, New Mexico, June 23{25, 1993. [5] Gerald Baumgartner and Vince Russo. README. Available by anonymous ftp from ftp.cs.purdue.edu, directory pub/gb, Department of Computer Sciences, Purdue University, 1992. [6] Gerald Baumgartner and Ryan D. Stansifer. A Proposal to Study Type Systems for Computer Algebra. RISC-Linz Report 90-87.0, Research Institute for Symbolic Computation, Linz, Austria, March 1990. [7] Andrew Black, Norman Hutchinson, Eric Jul, and Henry Levy. \Object structure in the Emerald system." In Proceedings of the OOPSLA '86 Conference on Object-Oriented Programming Systems, Languages, and Applications, Portland, Oregon, 29 September - 2 October 1986. SIGPLAN Notices, Vol. 21, No. 11, November, pp. 78{86. [8] Peter S. Canning, William R. Cook, Walter L. Hill, and Walter G. Oltho . \Interfaces for strongly-typed object-oriented programming." In Proceedings of OOPSLA '89 Conference on Object-Oriented Programming Systems, Languages, and Applications, New Orleans, Louisiana, 1{6 October 1989. SIGPLAN Notices, Vol. 24, No. 10, October 1989, pp. 457{467. 15

[9] Luca Cardelli, James Donahue, Lucille Glassman, Mick Jordan, Bill Kalsow, Greg Nelson. \Modula-3 Language De nition." ACM SIGPLAN Notices, Vol. 27, No. 8, August 1992, pp. 15{43. [10] Luca Cardelli and Peter Wegner. \On understanding types, data abstraction, and polymorphism." Computing Surveys, Vol. 17, No. 4, December 1985, pp. 471{522. [11] William R. Cook. \Interfaces and speci cations for the Smalltalk-80 collection classes." In Proceedings of OOPSLA '92 Conference on ObjectOriented Programming Systems, Languages, and Applications, Vancouver, Canada, 18{22 October 1992. SIGPLAN Notices, Vol. 27, No. 10, October 1992, pp. 1{15. [12] William R. Cook, Walter L. Hill, and Peter S. Canning. \Inheritance is not subtyping." In Proceedings of 17th Annual ACM Symposium on Principles of Programming Languages, San Francisco, 17{19 January 1990, pp. 125{135. [13] James Donahue and Alan Demers. \Data types are values." ACM Transactions on Programming Languages and Systems, Vol. 7, No. 3, July 1985, pp. 426{445. [14] Margaret A. Ellis and Bjarne Stroustrup. The Annotated C++ Reference Manual. Reading, Massachusetts: Addison-Wesley, 1990. [15] Adele Goldberg and David Robson. Smalltalk-80: The Language and Its Implementation. Reading, Massachusetts: Addison-Wesley, 1983. [16] Elana D. Granston and Vincent F. Russo. \Signature-based polymorphism for C++." In Proceedings of the USENIX C++ Technical Conference, Washington, D.C., 1991. [17] Paul Hudak and Joseph H. Fasel. \A gentle introduction to Haskell." ACM SIGPLAN Notices, Vol. 27, No. 5, May 1992, Section T. [18] Paul Hudak et al. \Report on the programming Language Haskell: A non-strict, purely functional language, version 1.2." ACM SIGPLAN Notices, Vol. 27, No. 5, May 1992, Section R. [19] Wilf R. LaLonde, Dave A. Thomas, and John R. Pugh. \An exemplar based Smalltalk." In Proceedings of OOPSLA '86 Conference on 16

Object-Oriented Programming Systems, Languages, and Applications, Portland, Oregon, 29 September - 2 October 1986. SIGPLAN Notices, Vol. 21, No. 11, November, pp. 322{330.

[20] Konstantin Laufer. Polymorphic Type Inference and Abstract Data Types. Ph.D. thesis, New York University, 1992. [21] David B. MacQueen. \Modules for Standard ML." Polymorphism, Vol. 2, No. 2, 1985. [22] David B. MacQueen. \An implementation of Standard ML modules." In Proceedings of the 1988 ACM Conference on Lisp and Functional Programming, Snowbird, Utah, 25{27 July 1988. Association for Computing Machinery, pp. 212{223. [23] Per Martin Lof. \Constructive mathematics and computer programming." In Proceedings of the 6th International Congress for Logic, Methodology, and Philosophy of Science. Amsterdam: North Holland, 1982, pp. 153{175. [24] Bertrand Meyer. Object-Oriented Software Construction. New York, New York: Prentice-Hall, 1987. [25] Robin Milner and Mads Tofte. Commentary on Standard ML. Cambridge, Massachusetts: The MIT Press, 1991. [26] Robin Milner, Mads Tofte, and Robert Harper. The de nition of Standard ML. Cambridge, Massachusetts: The MIT Press, 1990. [27] John Mitchell, Sigurd Meldal, and Neel Madhav. \An extension of Standard ML modules with subtyping and inheritance." In Conference Record of the 18th Annual ACM Symposium on Principles of Programming Languages, Orlando, Florida, 21{23 January 1991, pp. 270{278. [28] Didier Remy. \Typechecking records and variants in a natural extension of ML." In Conference Record of the 16th Annual ACM Symposium on Principles of Programming Languages, 1989, pp. 60{76. [29] Craig Scha ert et al. \An introduction to Trellis/Owl." In Proceedings of the OOPSLA '86 Conference on Object-Oriented Programming Systems, Languages, and Applications, Portland, Oregon, 29 September{2 October 1986. SIGPLAN Notices, Vol. 21, No. 11, November, pp. 9{16. 17

[30] Alan Snyder. \Encapsulation and inheritance in object-oriented programming languages." In Proceedings of OOPSLA '86 Conference on Object-Oriented Programming Systems, Languages, and Applications, Portland, Oregon, 29 September - 2 October 1986. SIGPLAN Notices, Vol. 21, No. 11, November, pp. 38{45. [31] Ryan Stansifer. \Type inference with subtypes." In Conference Record of the 15th Annual ACM Symposium on Principles of Programming Languages, San Diego, January 1988. [32] Robert S. Sutor and Richard D. Jenks. \The type inference and coercion facilities in the Scratchpad II interpreter." In Proceedings of the SIGPLAN '87 Symposium on Interpreters and Interpretive Techniques, 24{ 26 June 1987, St. Paul, Minnesota. SIGPLAN Notices, Vol. 22, No. 7, 1987, pp. 56{63. [33] Mitchell Wand. \Complete type inference for simple objects." In Proceedings of the 2nd IEEE Symposium on Logic in Computer Science, 1987, pp. 37{44. Corrigendum in Proceedings of the 3rd IEEE Symposium on Logic in Computer science, 1988, p. 132. [34] Stephen M. Watt, Richard D. Jenks, Robert S. Sutor, and Barry M. Trager. The Scratchpad II Type System: Domains and Subdomains. Manuscript, Mathematical Sciences Department, IBM Thomas J. Watson Research Center, Yorktown Heights, NY, 1987. [35] Peter Wegner. \Dimensions of object-based language design." In Proceedings of OOPSLA '87 Conference on Object-Oriented Programming Systems, Languages, and Applications, Orlando, Florida, 4{8 October 1987. SIGPLAN Notices, Vol. 22, No. 12, December 1987, pp. 168{182. [36] Niklaus Wirth. Programming in Modula-2. Texts and Monographs in Computer Science. Berlin-Heidelberg, Germany: Springer Verlag, 1985.

18