From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: ad hoc vs. parametric polymorphism (Was Re: comparing object-oriented platforms)
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Fri, 9 Oct 1992 19:25:53 GMT

In article <1992Oct7.200903.19397@beaver.cs.washington.edu> chambers@cs.washington.edu writes:
>In article <1992Oct6.190729.24367@ucc.su.OZ.AU>, maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>|> 
>|> 	Its very difficult for me to see how you can use
>|> an array of polymorphic numbers to *do* anything. I dont
>|> believe numbers can be characterised as "OO-style" objects.
>
>I think numbers are a fine example of ad hoc polymorphism.  

	I dont know of any system that can add two numbers
given a fixed interface protocol and arbitrary implementations.
On the other hand, OO clearly supports testing arbitrary numbers
for zero.

>There are
>a number of different possible representations for numbers, but these
>representations share a common protocol.  

	Number + Number -> Number

will do fine.

>
>In a purely OO language, new numeric representations can be added to
>the system by programmers, as long as they continue to support the
>expected protocol.  

	I dont think so. First, I haveto ask what a 'purely OO'
language is? Second, bear with me, I'm only a C++ programmer :-)
(I tend to think C++is class oriented, not object oriented)

	I require that you be able to add an implementation
of a type independently of any other implementations.
I defy you to write a + method for a new representation
of a number that adds to the number any other representation
of a number, including ones you havent written yet.

	This for me is a requirement for OO ness.
Clearly you can meet this requirement for a test for zero.

>This is not the case in languages such as SML.
>Haskell is better at this with its type classes.
>
>|> 	For example, to test if such an array is sorted,
>|> you need a comparison routine. One way to write such a
>|> routine is to convert each number to a fixed predefined
>|> numeric type (say double float), and this method
>|> is indeed polymorphic (that is, the conversion routine is).
>
>Blech.  Both slow and inaccurate.  

	Oh, I agree, but I'm just covering myself because this
actually IS a truly OO solution. It works for ANY representation
of a number for the + or < or any other operation. In fact,
having defined these operations on the universal type,
you only need to define two conversions for any other
representation.

>But this is a comment on the
>approach, not language support.  This approach could be implemented in
>languages with ad hoc polymorphism just fine.  

	Yes, and it is the ONLY way that works properly.
(If you disagree it must be with the defintion of 'works properly' :-)

>
>|> 	I dont believe it can be done without the predefined
>|> universal numeric type. Of course, if you fix in advance
>|> the number classes to say Integer, Rational, Float, then you can
>|> write 9 comparison routines to do the job and dispatch
>|> to the correct one, but this isnt polymorphism in my books,
>|> or rather, it isnt object oriented. The reason of course
>|> is that to add a new type Double you have to know the types
>|> you already have---they are coupled when OO requires
>|> each type be self-contained (encapsulated).
>
>For binary operations where the algorithm depends on the
>implementation of more than one argument, some form of multiple
>dispatching, either through multi-methods or simulated through double
>dispatching, would be used.  This may require the implementor to know
>in advance the various kinds of numbers involved in order to compare
>them, but that's a necessary part of the problem.  OO won't magically
>make this disappear, but the need to write e.g. 9 comparison routines
>would be present in a non-OO solution, too.  OO doesn't prohibit such
>situations.

	One of the fundamental goals of computer science is
the modular implementation of abstract data types. That is,
I give one or more types T1, T2 etc, and give them some
operations which I define axiomatically.

	The goal is to implement the ADT, such implementation
must be independent of other implementations---they must be
self contained.

	Now for some ADTs, for example vectors, it does not
make sense to add two vectors from different spaces. But for
'number' it does (if I suitable constrain what I mean by a number).

	So I must be able to calculate A+B where I dont care
about how A and B are implemented.

	OO cant do this. (Except with my univeral number)
 
	Defining all the cases for multimethods is 
exactly what we dont want. This is the big 'switch'
statement.

>
>As far as encapsulation of objects goes, I'm working on a
>multi-method-based OO language named Cecil that attempts to keep
>objects encapsulated in the presence of multi-methods.  The basic idea
>is that a multi-method is inside the encapsulation boundaries of each
>of the classes on which it specializes.  Classes don't have to be
>completely exposed to all objects to support multi-methods (as in 
>CLOS).  Instead, the internals of classes are only exposed to methods
>that specialize on them.  These ideas are described in more detail in
>my ECOOP'92 paper.
>

	I have read a description of Cecil, but there was no
encapsulation at all, that is, the methods were not 'captured'
inside of objects. If you have advanced the system to be
able to do this I would be most interested. (I liked the ideas
in Cecil very much)

	As a C++ programmer (yes I know its not OO), I have a different
idea of polymorphism than a programmer of a dynamic system. In particular,
in C++ we have separately compiled modules, and in particular,
we have modules that can be put in service (closed) yet extended (open).
The closed modules (base classes) can be referenced in
routines that say sort an array. The afterwards we can derive
a new class from the base, make objects of that class, and call
the original sort routine.

	The critical principle which makes this work is 
the open/closed principle (Meyer). It is pretty clear
that you cant have multimthods in such a system,
at least ones of the form where you need to write 9
routines, so any need for multimethods indicate that OO is flawed.

	This is not true in dynamic systems because there are no
modules to close, so OO works there, but unfortunately,
that means you cant have reusable modules. If you cant
write reusable routines that operate on an ADT you havent
solved the fundamental problem.

	It's quite possible there is no solution.

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------