English version
Accueil     Ŕ propos     Téléchargement     Ressources     Contactez-nous    

Ce site est rarement mis ŕ jour. Pour les informations les plus récentes, rendez-vous sur le nouveau site OCaml ŕ l'adresse ocaml.org.

Browse thread
Fwd: "ocaml_beginners"::[] Trouble combining polymorphic classes and polymorphic methods
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2007-02-28 (00:23)
From: Jacques Garrigue <garrigue@m...>
Subject: Re: [Caml-list] Fwd: "ocaml_beginners"::[] Trouble combining polymorphic classes and polymorphic methods
From: "Geoffrey Romer" <geoff.romer@gmail.com>
> [escalated from ocaml_beginners, where I got no response]
> I'm trying to create a polymorphic class 'a foo which has a
> polymorphic method that takes as a parameter another foo object, but
> one with arbitrary type. In other words, something like this:
> class virtual ['a] foo =
> object (self)
>   method virtual bar : 'b. 'b foo -> unit
> end;;
> When I try to compile this, though, I get a warning that I "cannot
> quantify 'b because it escapes this scope". When I drop the " 'b. " it
> compiles fine, but the reported type for bar is 'a foo -> unit; i.e.
> it's no longer polymorphic.
> Is there a problem with trying to make a method polymorphic with
> respect to the class type in this way? How can I make this work?

The reason it does not work is that recursive object types have to be
regular. That is, when using foo inside its own definition, the
parameters must be the same. Since 'a <> 'b, this fails.

This restriction is due to the structural typing of objects, and as
such it does not apply to records, which are nominal. So you can
  type 'a foo = { bar : 'b. 'b foo -> unit; }
which has basically the same meaning.

You can also mix classes and records:
  type 'a foo_t = <get : 'a; bar : 'b. 'b foo_r -> unit>
  and 'b foo_r = {foo: 'b foo_t}
This way, you only need to wrap foo objects in foo_r when you want to
pass them to bar.

If you want to define a class type rather than an object type (class
types are more versatile), you can use the following trick to create a
recursion between a class type and a normal type;

  module rec M : sig            
    class type ['a] foo = object
      method get : 'a
      method bar : 'b. 'b M.foo_r -> unit
    type 'a foo_r = {foo: 'a foo}
  end = M

You cannot define your virtual class directly inside the recursive
module, because it would require an implementation, but this can be
done easily afterwards:
  # class virtual ['a] foo = object (_ : 'a #M.foo) end;;
  class virtual ['a] foo :
    object method virtual bar : 'b M.foo_r -> unit method virtual get : 'a end

Hope this helps.

Jacques Garrigue