caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jerome Vouillon <Jerome.Vouillon@inria.fr>
To: Markus Mottl <mottl@miss.wu-wien.ac.at>
Cc: OCAML <caml-list@inria.fr>
Subject: Re: subtyping and inheritance
Date: Mon, 18 Jan 1999 20:55:42 +0100	[thread overview]
Message-ID: <19990118205542.06048@pauillac.inria.fr> (raw)
In-Reply-To: <199901151737.SAA21368@miss.wu-wien.ac.at>; from Markus Mottl on Fri, Jan 15, 1999 at 06:37:26PM +0100


> What I want to do is:
> 
> Compare terminals to terminals:
>   Via a method "compare", which is naturally defined in class "terminal"
>   This method calls methods in "other", which are only found in terminals
> 
> Compare nonterminal to nonterminal:
>   Via a method "compare", which is naturally defined in class "nonterminal"
>   This method calls methods in "other", which are only found in
>   nonterminals
> 
> Compare symbols to symbols:
>   Via a method "compare", which is naturally defined in class "symbol"
>   This method calls methods in "other", which are found in nonterminals
>   and terminals the like

So, you want to be able to select a method depending on two
objets. This is not directly possible, but you can encode it using two
successive method calls:

    class type symbol_t = object
      method x : int
    end and terminal_t = object
      inherit symbol_t
      method y : int
    end;;
    class symbol x = object (self : 'a)
      method x = x

      method compare (other : symbol) =
        other#compare_with_symbol (self :> symbol_t)
      method compare_with_symbol other = self#x = other#x
      method compare_with_terminal (other : terminal_t) = false
    end;;
    class terminal x y = object (self)
      inherit symbol x
      method y = y

      method compare (other : symbol) =
        other#compare_with_terminal (self :> terminal_t)
      method compare_with_symbol other = false
      method compare_with_terminal other =
        (self#x = other#x) && (self#y = other#y)
    end;;

> If I change your example into the direction I want, I would change class
> "terminal" e.g. as follows:
> 
>   class terminal = object (self)
>     inherit symbol
>     method x = "a"
>     method y = "y"
>     method compare (other : terminal) = self#y = other#y (* line 15 *)
>   end
> 
> Here, I compare terminals to each other with a totally different
> comparison method than the one found in "symbol".  Unfortunately, your
> example won't type check correctly anymore: the compiler generates the
> (certainly not correct) message:
> 
>   File "bla.ml", line 15, characters 47-52:
>   This expression has type terminal
>   It has no method y
> 
> But "terminal" *has* a method "y"!!! The problem is that "compare" has
> been instantiated in "symbol" with "symbol" as type parameter to "ord".
> Thus, the method "compare" has type "symbol -> bool".  The compiler still
> believes that "compare" should have this type, but wrongly takes the
> type information provided in the declaration of "compare" in "terminal",
> which declares "compare" to be of type "terminal -> bool". This results
> in the incorrect error message that "terminal" has no method "y".

Here is an explanation of this error message. Just before typing the
method "compare" in class "terminal", we know that its type must be
"symbol -> bool". However, we don't know anything about the type
"terminal" yet (this type will have to be a suitable instance of the
type of self, but this can only be checked once the whole class body
is typed). Then, the type constraint "(other : terminal)" tells the
compiler that the type "terminal" must be the same as the type of the
argument of the method, that is "symbol". This will not be possible,
but the compiler does not know it yet. Then, the type checking fails
because "other", of type "symbol" has no method "y".

I will try to provide a better error message.

>     class virtual ord = object (self:'self)
>       method virtual compare : 'self -> bool
>     end
>     
>     class symbol = object (self)
>       inherit ord
>     
>       val mutable symbol_order = 0
>       method symbol_order = symbol_order
>     
>       method compare other = self#symbol_order = other#symbol_order
>     end
>     
>     class terminal = object (self)
>       inherit symbol
>     
>       val mutable terminal_order = 0
>       method terminal_order = terminal_order
>     
>       method compare other = self#terminal_order = other#terminal_order
>     
>       initializer symbol_order <- 1
>     end
>     ;;
>     
>     (new terminal :> symbol)#compare new symbol
[...]
> Actually, the error message of the compiler for this example code is
> (in my eyes) also misleading. It says:
> 
>   File "bla.ml", line 26, characters 1-13:
>   This expression cannot be coerced to type
>     symbol = < compare : symbol -> bool; symbol_order : int >;
>   it has type
>     terminal =
>       < compare : terminal -> bool; symbol_order : int;
>         terminal_order : int >
>   but is here used with type
>     < compare : symbol -> bool; symbol_order : int; terminal_order : int >
>   Type
>     terminal =
>       < compare : terminal -> bool; symbol_order : int;
>         terminal_order : int >
>   is not compatible with type
>     symbol = < compare : symbol -> bool; symbol_order : int >
>   Only the first object type has a method terminal_order

Here is how you should understand this error message.  The method
"compare" in an object of class "terminal" has type "terminal ->
bool". Therefore, it can make use of the method "terminal_order" of
its argument. Thus, as the type "symbol" has no method
"terminal_order", the method "compare" cannot be given the type
"symbol -> bool". Hence, finally, the type "terminal" is not a subtype
of type "symbol", and the coercion is not possible.

-- Jérôme




  reply	other threads:[~1999-01-19 16:54 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-01-11 18:52 Markus Mottl
1999-01-15 15:02 ` Jerome Vouillon
1999-01-15 17:37   ` Markus Mottl
1999-01-18 19:55     ` Jerome Vouillon [this message]
1999-01-18 21:18       ` Markus Mottl
1999-01-20 11:50         ` Hendrik Tews
1999-01-25  0:08           ` Markus Mottl
1999-01-25 15:06             ` Musings on Obj.magic (Was: subtyping and inheritance) David Monniaux
1999-01-27 14:18             ` subtyping and inheritance Jerome Vouillon
1999-01-27 14:45               ` Markus Mottl
1999-01-28 19:40               ` Hendrik Tews
1999-01-27 14:28           ` Jerome Vouillon
1999-04-15 12:18 Giuseppe Castagna
1999-04-15 16:02 ` Markus Mottl
1999-04-20 12:38 ` Didier Remy
1999-04-20 15:06   ` Giuseppe Castagna
1999-04-21 12:18     ` Didier Remy

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=19990118205542.06048@pauillac.inria.fr \
    --to=jerome.vouillon@inria.fr \
    --cc=caml-list@inria.fr \
    --cc=mottl@miss.wu-wien.ac.at \
    /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).