Date: Fri, 13 Sep 1996 14:31:50 +0200 (MET DST)
From: Jerome Vouillon <vouillon@clipper.ens.fr>
Subject: Re: Closed Objects
To: Andrew Conway <arc@sequence.stanford.edu>
In-Reply-To: <199609121922.MAA19250@vegemite.Stanford.EDU>
Message-Id: <Pine.3.89.9609131323.A21177-0100000@vedette>
> class virtual runaround () as self : 'a =
> virtual null : bool
> virtual next : runaround
> virtual myself : runaround
> end;;
>
> (* Add a method. This DOESN'T compile in ocaml 1.01, but
> did compile in ocaml 1.00. The error message says that it
> is closed, but not marked closed.
>
> I don't want it to be closed. Is it impossible to return "self"
> in a non-closed class?
>
> *)
>
> class virtual run2 () as self =
> inherit runaround ()
> method myself = (self :> runaround)
> end;;
Coercion operator ( e :> t ) is not always general enough. What it does is
guess a type t' subtype of t independant of expression e, and then checks
the type of expression e is an instance of type t'. For instance, if
t = <x : int>, then t' = <x : int; ..>. In this case, any subtype of t is
an instance of type t'. But this is not always the case. Consider type
t = <x : 'a> as 'a. The types <x : 'b; y : int> as 'b and
<x : t; y : int> are both subtypes of this type, but they are not
instances of a common subtype of type t. So, one have to use a heuristic
to find a type t' that works in most cases (I have changed the algorithm
between ocaml 1.00 and ocaml 1.01, that's why your example compiles with
the first version, but not with the second version).
Let us come back to your example. You can see here the type t' guessed:
#fun x -> (x :> runaround);;
- : (< null : bool; next : 'a; myself : 'a; .. > as 'a) -> runaround = <fun>
\_________________________________________________/
t'
If you unify type t' with the type of self in class run2, you will get
type runaround. Indeed, method myself of self has type runaround, so
runaround = 'a (unification of types of myself)
= type of self
The type runaround is closed, hence the error message.
The workaround is to use the more general coercion operator ( e : t' :> t )
when the other one fails.
#class virtual run2 () as self =
# inherit runaround ()
# method myself = (self : #runaround :> runaround)
#end;;
class virtual run2 (unit) =
method myself : runaround
virtual null : bool
virtual next : runaround
end
Jerome