OCaml's subtyping better than advertised?

From: Donald Syme (Donald.Syme@cl.cam.ac.uk)
Date: Tue May 20 1997 - 16:22:28 MET DST

To: caml-list@inria.fr
Subject: OCaml's subtyping better than advertised?
Date: Tue, 20 May 1997 15:22:28 +0100
From: Donald Syme <Donald.Syme@cl.cam.ac.uk>
Message-Id: <E0wTpo6-0001pa-00@heaton.cl.cam.ac.uk>

Dear Caml-ers,

Here's something I've noticed while reading the O'Caml manual.
It seems to me that the O'Caml manual undersells itself on
one of the best features of the language: the separation of subtyping from
subclassing. In particular I mean that one object type
can be a subtype of another, without being related by the
inheritance hierarchy.

In some recent OO books (e.g. "Large Scale Programming in C++") recurring
OO-related difficulties like the "rigid base class problem" have been pointed
out. These frequently relate to the use of subclassing (implementation
inheritance) to achieve subtyping (sometimes called
interface inheritance, though this seems a little misleading as
interface inheritance is just one way of achieving subtyping).

It seems to me that one great advantage of the O'Caml
OO type system is that it frees the programmer to make use of
implementation inheritance in just those few places where
it proves helpful. (Indeed many would argue that implementation
inheritance is a bad thing per se, e.g. see the recent "language
wars" on comp.lang.<your-favourite-language>)

One thing I'm wondering is why the syntax for O'Caml types has no
way of specifying interface inheritance easily? For
example, I want to define some object type (nb. I'm defining
a type not a class):

  type widget = < windowid: unit -> int,
                  set_height: int -> unit,
                  height: unit -> int,
                  .. >;

[ Aside: at the moment I don't seem to be able to do this
  in O'Caml, without defining a class, because the type
  variable ".." is free. Perhaps there needs to be come
  mechanism for defining new object types with the same
  "#<type>" behaviour of the types generated by classes?
  This would then allow me to write "#widget" as a type
  without having defined a class widget (i.e. without
  having committed to an implementation) ]

If I then want to define some structural subtype of #widget
(nb. not necessarily implemented by a subclass), I have to write out all
the methods again:

  type textual_widget = < windowid: unit -> int,
                          set_height: int -> unit,
                          height: unit -> int,
                          insert : string * int -> unit,
                          get : int * int -> string
                          .. >;

Also, the documentation says that a
type like "#point" (for some point class) unifies with any subclass of
point. It seems worth emphasizing that such a type in fact unifies
with any object-type that has at least the methods from the class point,
whether or not the object-type is related by the interface hierarchy.

Speaking as someone who has done a fair bit of OO programming (in
C++ - bleah), I think this aspect of O'Caml's type system is fantastic.
The one other major thing that seems to be lacking (and no doubt hard to
implement efficiently) is some kind of runtime typechecking for coercions
down the subtype hierarchy. [ The manual incorrectly
states that ":>" coerces to subtypes - in fact it coerces to
supertypes]. Whether or not such casts
are "necessary" could no doubt be a matter of vigorous debate
given the static-typing tradition of the ML languages, but
to me they seem unavoidable in some situations. I guess you
can always use OCaml's "magic" and (as in C++) cross your fingers.

Don Syme

P.S. Apologies for no french version.

This archive was generated by hypermail 2b29 : Sun Jan 02 2000 - 11:58:11 MET