From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id p2JJlRCv026669 for ; Sat, 19 Mar 2011 20:47:27 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AuAGAF+khE1V2gB4Vmdsb2JhbACERKE7ARYLDxcliE2pDpAaDYEag0V3BJBS X-IronPort-AV: E=Sophos;i="4.63,211,1299452400"; d="scan'208";a="103093922" Received: from emailfrontal1.citycable.ch ([85.218.0.120]) by mail1-smtp-roc.national.inria.fr with SMTP; 19 Mar 2011 20:47:21 +0100 X-Alinto-smtpauth-localdomain: Yes Received: from seldon (unknown [85.218.93.111]) (Authenticated sender: guillaume.yziquel@citycable.ch) by emailfrontal1.citycable.ch (Postfix) with ESMTPA id 2B70212C5BA; Sat, 19 Mar 2011 20:47:20 +0100 (CET) Received: from yziquel by seldon with local (Exim 4.72) (envelope-from ) id 1Q125d-0003ri-Hz; Sat, 19 Mar 2011 20:45:33 +0100 Date: Sat, 19 Mar 2011 20:45:33 +0100 From: Guillaume Yziquel To: Raphael Proust Cc: caml-list@yquem.inria.fr Message-ID: <20110319194533.GT20405@localhost> References: <201103191648.40345.raphlalou@gmail.com> <20110319174803.GP20405@localhost> <201103192020.36314.raphlalou@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <201103192020.36314.raphlalou@gmail.com> User-Agent: Mutt/1.5.20 (2009-06-14) Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by walapai.inria.fr id p2JJlRCv026669 Subject: Re: [Caml-list] Recursive Parametric class type Typing Le Saturday 19 Mar 2011 à 20:20:36 (+0100), Raphael Proust a écrit : > Le samedi 19 mars 2011 18:48:03, Guillaume Yziquel a écrit : > > Le Saturday 19 Mar 2011 à 16:48:40 (+0100), Raphael Proust a écrit : > > > Hi list, > > > > > > Trying to bind a javascript library for js_of_ocaml, I encountered the > > > following pattern (here drastically simplified): > > > > > > class type ['t] c = > > > object > > > method plus: 't -> unit > > > method minus: unit -> 't > > > method container: unit -> container > > > end > > > and container = > > > object > > > method int: unit -> int c > > > method string: unit -> string c > > > end > > > > > > The following error is raised at compile time: > > > Error: This type string should be an instance of type int > > > > > > In the use case: > > > - instead of [int] and [string] there are six different [class type]s; > > > - [classe type]s have more methods; and > > > - there are additional recursive [class type]s > > > > > > Why is there such a limitation on the types? Is there a work around that > > > wouldn't induce (too much) code duplication? > > > > The reason why there is this behaviour is unification within the 'and' > > declaration. method int says that 't in ['t] c is of type int, > > therefore it should also be an int c in method string instead of a > > string c. > > It makes sens… > > > > > Workaround: Use recursive modules. They are a solution for keeping > > recursion while breaking type unification. Something in the taste of: > > > > yziquel@seldon:~$ ocaml > > Objective Caml version 3.12.0 > > > > # module rec Q : sig > > class type ['w] e = object method r : 'w end > > end = struct > > class type t = object > > method z : int Q.e > > method u : string Q.e > > end > > class type ['w] e = object method r : 'w end > > end;; > > module rec Q : sig class type ['a] e = object method r : 'a end end > > > > Not sure if this fits your bill when it comes to avoiding code > > duplication. > > Because I want both [t] and [e] available (in fact there are 4 recursive classes > I want available), I made several recursive modules. Beside having each type > written twice, it still had a typing error: > > Error: In the definition of Paper.paper, type > Svg.circle_attr Elem.element > should be > 'a Elem.element Noticed it too. Do not know where that comes from. > I found a (half satisfying) workaround using the fact that methods that makes > parametrization necessary and methods that makes recursivity necessary do not > intersect. So I ended up with a parametric class that is not part of the > recursion. The "polymorphic recursion" of sort is broken but I need a different > class for each type I want to instantiate the type with. A perhaps more natural way would be to use object types. Something like type t = private < z : int e; u : string e > is easier to declare, and easier to declare recursively. Drawbacks: you still have issues when you want to declare the meat of your classes; and doesn't work well with ocamldoc. -- Guillaume Yziquel