From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id CFFF0BBC4 for ; Fri, 3 Apr 2009 22:53:37 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AsYFAJMT1knZSMDjZmdsb2JhbACBUpRRDQsDBQkPBbhHhA8Ghzk X-IronPort-AV: E=Sophos;i="4.39,321,1235948400"; d="scan'208";a="25598281" Received: from fmmailgate02.web.de ([217.72.192.227]) by mail3-smtp-sop.national.inria.fr with ESMTP; 03 Apr 2009 22:53:36 +0200 Received: from smtp08.web.de (fmsmtp08.dlan.cinetic.de [172.20.5.216]) by fmmailgate02.web.de (Postfix) with ESMTP id 52207FC74D53; Fri, 3 Apr 2009 22:53:36 +0200 (CEST) Received: from [78.43.226.218] (helo=frosties.localdomain) by smtp08.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #277) id 1LpqON-0000mP-00; Fri, 03 Apr 2009 22:53:36 +0200 Received: from mrvn by frosties.localdomain with local (Exim 4.69) (envelope-from ) id 1LpqON-0006BD-C5; Fri, 03 Apr 2009 22:53:35 +0200 From: Goswin von Brederlow To: Jacques GARRIGUE Cc: goswin-v-b@web.de, caml-list@yquem.inria.fr Subject: Re: [Caml-list] Bug? Constraints get ignored in methods References: <87ab71ic1f.fsf@frosties.localdomain> <20090402.173911.68542703.garrigue@math.nagoya-u.ac.jp> Date: Fri, 03 Apr 2009 22:53:35 +0200 In-Reply-To: <20090402.173911.68542703.garrigue@math.nagoya-u.ac.jp> (Jacques GARRIGUE's message of "Thu, 02 Apr 2009 17:39:11 +0900 (JST)") Message-ID: <874ox5jw6o.fsf@frosties.localdomain> User-Agent: Gnus/5.110006 (No Gnus v0.6) XEmacs/21.4.21 (linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Sender: goswin-v-b@web.de X-Sender: goswin-v-b@web.de X-Provags-ID: V01U2FsdGVkX1+iJsuK/gVN2To9N9AwgkT7m/O4YhU5wa44gx9L R7+EIAHhBixJ3gRsKQGK/RrzhCJcDquN2vqsjTyW50sVfJKG7p vspLQQKQc= X-Spam: no; 0.00; bug:01 subset:01 ocaml:01 subset:01 val:01 mutable:01 foo:01 foo:01 node:01 node:01 coercions:01 ocaml:01 val:01 mutable:01 verbose:01 Jacques GARRIGUE writes: > From: Goswin von Brederlow > >> 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 foo = object inherit base method foo = () end;; > [...] >> # let a = new base in >> let b = new foo in >> a#set_next (Some (b :> base_type));; >> - : unit = () >> >> 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: > >>>From your other posts I gather that your objects have a uniform > interface once they are in the list, and a specific interface just after > creating them. Hopefully you never need to recover the specific > interface from an object in a list (if that were the case, then I > strongly suggest using normal sum types...) There will be more than one way to get an object. One is through the list and that only uses the common methods. The other is through a tree where the specific type is known at compile time. That is why I need the list internal to the objects. Because some method will walk through the tree and obsolete a node. That node then needs to be removed from the list as well as from the tree. > You don't want to write the coercions. That's natural. I see two ways > out. One is to realize that a method is just a weaker function, so > just write a function doing the coercion: > > let set_next (x : #base_type) y = > x#set_next (Some (y :> base_type)) > > You might not like using a function, but you just have to realize that > methods are kind of second class in ocaml... > > If you really want to stick to methods only (because of library > design, for instance), then a clever trick is to use a coercion > methods: > > class virtual base_type = > object (self) > val mutable virtual next : base_type option Why is next virtual here? Doesn't that require that anyone inheriting base_type has to define their own version of next? Seems like needless duplication. > method virtual set_next_base : base_type option -> unit > method as_base = (self :> base_type) > method set_next : 'a. as 'a -> unit = > fun x -> self#set_next_base x#as_base > end > > This may seem verbose here, but self-coercion methods are a good idea > anyway. > > Hope this helps, > > Jacques Garrigue This helps a lot. Nice little trick to go through an immediate object type. MfG Goswin