caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Peng Zang <peng.zang@gmail.com>
To: caml-list@yquem.inria.fr
Cc: Goswin von Brederlow <goswin-v-b@web.de>
Subject: Re: [Caml-list] Bug? Constraints get ignored in methods
Date: Tue, 31 Mar 2009 21:24:36 -0400	[thread overview]
Message-ID: <200903312124.38637.peng.zang@gmail.com> (raw)
In-Reply-To: <87ab71ic1f.fsf@frosties.localdomain>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

Here's an example of how constraints are specified for polymorphic methods.  
In this example I define a list type which can compare to anything that is 
foldable.

  class type ['a] foldable = object
    method foldl : 'z. ('z -> 'a -> 'z) -> 'z -> 'z
  end

  class type ['a] mylist = object
    inherit ['a] foldable
    method compare : 'z. ('a #foldable as 'z) -> int
  end

Direct application to your example would not work:

  # class virtual base = object
      method virtual setnext : 'a. (#base as 'a) option -> unit
    end
  Error: This type scheme cannot quantify 'a : it escapes this scope.
  #

OCaml does not allow the recursive reference when the method is polymorphic.  
One option is to just deal with coercions or a function that does it for you:

  class virtual base = object
    method virtual setnext : base option -> unit
  end

  let callsetnext (obj:#base) (n:#base option) = 
    obj#setnext (n :> base option)

Another option is to factor out the basic operations you need like the in list 
example.  I didn't make the list compare method work with other lists, I made 
it more general to work with anything that is foldable.  This avoids the 
recursive reference because foldable is defined ahead of time.

Cheers,

Peng



On Tuesday 31 March 2009 06:05:00 pm Goswin von Brederlow wrote:
> Hi,
>
> I want to keep a linked list of structures that have a common subset
> of functionality. I thought this would be a good use of ocaml objects.
> A base class with the common subset of functionality and methods to
> link them. And then derived classes for the specific types. Most
> simplified it looks like this:
>
> # class type base_type = object val mutable next : base_type option method
> set_next : base_type option -> unit end;; class type base_type =
>   object
>     val mutable next : base_type option
>     method set_next : base_type option -> unit
>   end
>
> # class base : base_type = object val mutable next = None method set_next n
> = next <- n end;; class base : base_type
>
> # class foo = object inherit base method foo = () end;;
> class foo :
>   object
>     val mutable next : base_type option
>     method foo : unit
>     method set_next : base_type option -> unit
>   end
>
> # let a = new base in
>     let b = new foo in
>       a#set_next (Some (b :> base_type));;
> - : unit = ()
>
> # let a = new base in
>     let b = new foo in
>       a#set_next (Some b);;
>                        ^
> Error: This expression has type foo but is here used with type base_type
>        The second object type has no method foo
>
> This last error isn't nice. I don't want to have to cast the objects
> all the time. So I thought there must be a better way using
> polymorphic methods with a constraint. But here is where everything
> breaks down. First lets look at just the set_next method:
>
> # class type virtual vbase_type = object method virtual set_next : 'a. 'a
> option -> unit constraint 'a = #vbase_type end;; class type virtual
> vbase_type =
>   object method virtual set_next : 'a option -> unit end
>
> # class virtual vbase : vbase_type = object method virtual set_next : 'a.
> 'a option -> unit constraint 'a = #vbase_type end;; class virtual vbase :
> vbase_type
>
> # class base = object inherit vbase method set_next _ = () end;;
> class base : object method set_next : 'a option -> unit end
>
> # let b = new base;;
> val b : base = <obj>
>
> # b#set_next (Some 1);;
> - : unit = ()
>
> Huh? That should not work. 1 is not a superset of #vbase_type. The
> constraint gets completly ignored by ocaml. Adding back the next gives
> further problems:
>
> # class type virtual vbase_type = object val mutable next : #vbase_type
> option method virtual set_next : 'a. 'a option -> unit constraint 'a =
> #vbase_type end;; class type virtual vbase_type =
>   object
>     val mutable next : #vbase_type option
>     method virtual set_next : 'a option -> unit
>   end
>
> # class virtual vbase : vbase_type = object val mutable next = None method
> virtual set_next : 'a. 'a option -> unit constraint 'a = #vbase_type end;;
> class virtual vbase : vbase_type
>
> # class base = object inherit vbase
>     method set_next n = next <- (n :> vbase_type option) end;;
>                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Error: This method has type #vbase_type option -> unit
>        which is less general than 'a. 'a option -> unit
>
> Again I  blame ocaml for dropping the constraint. Given the constraint
> the type would be correct.
>
>
>
> So how do I have to specify the set_next method that any superset of
> #base_type will be accepted as argument? Or is that a bug in ocaml and
> my syntax is perfectly fine?
>
> MfG
>         Goswin
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)

iD8DBQFJ0sJWfIRcEFL/JewRAr9iAKDXaZNlIZDlCdTaxWrIy7+5nObIZgCeIJ2d
qcvcX2pc/F899JuMgRa3S4A=
=lNOb
-----END PGP SIGNATURE-----


  parent reply	other threads:[~2009-04-01  1:24 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-31 22:05 Goswin von Brederlow
2009-03-31 23:01 ` [Caml-list] " Martin Jambon
2009-03-31 23:12   ` Martin Jambon
2009-03-31 23:52   ` Goswin von Brederlow
2009-04-01  0:08   ` Goswin von Brederlow
2009-04-01 11:41     ` Martin Jambon
2009-04-01 15:57       ` Goswin von Brederlow
2009-04-01 18:45         ` Martin Jambon
2009-04-01  1:24 ` Peng Zang [this message]
2009-04-01  3:25   ` Goswin von Brederlow
2009-04-02  8:39 ` Jacques GARRIGUE
2009-04-03 20:53   ` Goswin von Brederlow
2009-04-06  4:30     ` Jacques Garrigue

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=200903312124.38637.peng.zang@gmail.com \
    --to=peng.zang@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    --cc=goswin-v-b@web.de \
    /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).