Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Recursive classes are impossible?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Alessandro Baretta <alex@b...>
Subject: Re: [Caml-list] Recursive classes are impossible?


Gerd Stolpmann wrote:
> On 2002.06.24 15:59 Alessandro Baretta wrote:
> 
> What's going on? broccoli is not a subtype of tree, although it "only"
> adds a new method, which is normally no hindrance.
> 
> Why is broccoli not a subtype of tree? The method set_children does not
> fulfill the contravariance rule. 

Why, yes! Of course, I should have thought about 
inheritance. It did not occur to me that maybe the "more or 
less impossible" should refer to inheritance. But of course, 
inheritance has some typing idiosyncrasies in "ordinary" C++ 
as well.

class Tree {
	Tree *left, *right
}

This is already enough to get into trouble, 'cause you need 
to get into the nasty business of type casting, which very 
soon gets out of control. Of course C++ works under the 
assumption that anything anything can be cast to anything 
else; so you actually have the expressive power to get 
"classy" trees and the like. What you don't get in C++ is 
the ability to define a type variable and impose the 
constraint that it be equal to the type of the current 
class. That is, you can't write

class Tree {
	this_class *left, *right
}

which is the meaning of (self:'self) in you declaration of 
class tree in O'Caml. Is this not the real problem?
****
Hmmm... apparently not. I tried with the following code, 
which seems rather intuitively inheritance savvy.

class tree =
	object (s)
	val mutable ch = ( [] : tree list )
	method get = ch
	method set x = ch <- x
end;;

class broccoli =
	object (s)
	inherit tree
	method color = "green"
end;;
	
let b = new broccoli
and t = new tree;;

But even this way "t # set b" and "b # set b" both fail. 
Now, without the covariance of 'self in the formal parameter 
of method set, I would expect the compiler to consider b to 
be truly a subtype of t, but this is not the case, although 
I am allowed to explicitly upcast b to tree type and write

t # set [(b :> tree)];;
b # set [(b :> tree)];;

And this is what I get:

# t # set [(b :> tree)];;
- : unit = ()
# b # set [(b :> tree)];;
- : unit = ()
# t # set [b];;
This expression has type
   broccoli = < color : string; get : tree list; set : tree 
list -> unit >
but is here used with type
   tree = < get : tree list; set : tree list -> unit >
Only the first object type has a method color
# b # set [b];;
This expression has type
   broccoli = < color : string; get : tree list; set : tree 
list -> unit >
but is here used with type
   tree = < get : tree list; set : tree list -> unit >
Only the first object type has a method color


Why is it that an explicit upcast is needed?

> That means: You cannot define classes with methods whose arguments
> refer recursively to the class, and extend the class definitions later
> by inheritance. This is the reason why PXP does not have a DOM-like
> interface that can be extended by inheritance.
> 
> See the thread http://caml.inria.fr/archives/200111/msg00302.html for
> more explanations of subtyping rules.
> 
> Gerd

Thank you very much.

Alex

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners