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-----
next prev 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