caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Gerd Stolpmann <info@gerd-stolpmann.de>
To: Alessandro Baretta <alex@baretta.com>
Cc: Ocaml <caml-list@inria.fr>
Subject: Re: [Caml-list] Recursive classes are impossible?
Date: Mon, 24 Jun 2002 23:34:19 +0200	[thread overview]
Message-ID: <20020624233419.C760@ice.gerd-stolpmann.de> (raw)
In-Reply-To: <3D1725D9.7060409@baretta.com>; from alex@baretta.com on Mon, Jun 24, 2002 at 15:59:53 +0200


On 2002.06.24 15:59 Alessandro Baretta wrote:
>  > Due to the typing system it is more or less impossible to
>  > derive recursive classes in O'Caml. To get around this, it
>  > is common practice to put the modifiable or extensible
>  > part of recursive objects into parallel objects.
> <http://www.ocaml-programming.de/packages/documentation/pxp/manual/x550.html#AEN582>
> 
> Hmmm... Now I am no object specialist, but this sounds a 
> little weird to me. Now, let's see, doesn't the following 
> code show that recursive classes are indeed possible in 
> O'Caml? Or have I completely misunderstood what is meant by 
> recursive object?
> 
> class ['a] broccoli =
> 	object (s)
> 	val mutable portion = None;
> 	method set (x:'a option) = portion <- x
> end;;
> 
> let broccolo = new broccoli in
> 	broccolo#set (Some new broccoli);;
> 
> let broccolo = new broccoli in
> 	broccolo#set (Some broccolo);;
> 
> Sorry for mentioning broccoli, but it seemed appropriate 
> given the recursive nature of their geometry.

No, this is not the problem. Try the following:

class tree =
object(self:'self)
  val mutable v = (None : int option)
  val mutable ch = ([] : 'self list)
  method get = v
  method set x = v <- x
  method children = ch
  method set_children x = ch <- x
end

This definition works at the first glance, but if you try to
inherit from this class and subtype this class at the same
time, you will run into problems.

class broccoli =
object
  inherit tree
  method color = "green"
end

# let t = new tree;;
val t : tree = <obj>
# let b = new broccoli;;
val b : broccoli = <obj>
# t # set_children [b];;
This expression has type
  broccoli =
    < children : broccoli list; color : string; get : int option;
      set : int option -> unit; set_children : broccoli list -> unit >
but is here used with type
  tree =
    < children : tree list; get : int option; set : int option -> unit;
      set_children : tree list -> unit >
Only the first object type has a method color
# t # set_children [ (b :> tree) ];;
This expression cannot be coerced to type
  tree =
    < children : tree list; get : int option; set : int option -> unit;
      set_children : tree list -> unit >;
it has type
  broccoli =
    < children : broccoli list; color : string; get : int option;
      set : int option -> unit; set_children : broccoli list -> unit >
but is here used with type
  < children : broccoli list; color : string; get : int option;
    set : int option -> unit; set_children : tree list -> unit >
Type
  broccoli =
    < children : broccoli list; color : string; get : int option;
      set : int option -> unit; set_children : broccoli list -> unit >
is not compatible with type
  tree =
    < children : tree list; get : int option; set : int option -> unit;
      set_children : tree list -> unit > 
Only the first object type has a method color

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. This rule is a general subtyping rule,
and here it would mean that for all methods m:

- if broccoli.m has the function type s -> t
- and if tree.m has the function type u -> v
- the type u must be a subtype of s, and t must be a subtype of v.

broccoli.set_children has the type broccoli list -> unit,
and tree.set_children has the type tree list -> unit, but
tree list is not a subtype of broccoli list because tree is
not a subtype of broccoli. This means: if you want to show that 
broccoli is a subtype of tree, you need the assumption that tree is a
subtype of broccoli - this works only if both types are identical.
And the cause for this strange result is that the argument of the
method set_children refers recursively to the class type.

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
-- 
----------------------------------------------------------------------------
Gerd Stolpmann      Telefon: +49 6151 997705 (privat)
Viktoriastr. 45             
64293 Darmstadt     EMail:   gerd@gerd-stolpmann.de
Germany                     
----------------------------------------------------------------------------
-------------------
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


  reply	other threads:[~2002-06-24 21:34 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-24 13:59 Alessandro Baretta
2002-06-24 21:34 ` Gerd Stolpmann [this message]
2002-06-24 23:55   ` james woodyatt
2002-06-25 23:48   ` Alessandro Baretta
2002-06-26  2:43     ` John Prevost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20020624233419.C760@ice.gerd-stolpmann.de \
    --to=info@gerd-stolpmann.de \
    --cc=alex@baretta.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).