Version française
Home     About     Download     Resources     Contact us    
Browse thread
Bug? Constraints get ignored in methods
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Peng Zang <peng.zang@g...>
Subject: Re: [Caml-list] Bug? Constraints get ignored in methods
-----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-----