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 mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id 3E97BBBC4 for ; Wed, 1 Apr 2009 17:57:33 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjwCACIs00nZSMDqi2dsb2JhbACBU5RBAQEBCgsKBw8FujKDewY X-IronPort-AV: E=Sophos;i="4.39,307,1235948400"; d="scan'208";a="23741782" Received: from fmmailgate03.web.de ([217.72.192.234]) by mail2-smtp-roc.national.inria.fr with ESMTP; 01 Apr 2009 17:57:32 +0200 Received: from smtp08.web.de (fmsmtp08.dlan.cinetic.de [172.20.5.216]) by fmmailgate03.web.de (Postfix) with ESMTP id 5B13BF9D814B; Wed, 1 Apr 2009 17:57:32 +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 1Lp2om-0005dD-00; Wed, 01 Apr 2009 17:57:32 +0200 Received: from mrvn by frosties.localdomain with local (Exim 4.69) (envelope-from ) id 1Lp2oi-0003xY-NA; Wed, 01 Apr 2009 17:57:28 +0200 From: Goswin von Brederlow To: Martin Jambon Cc: Goswin von Brederlow , caml-list@yquem.inria.fr Subject: Re: [Caml-list] Bug? Constraints get ignored in methods References: <87ab71ic1f.fsf@frosties.localdomain> <49D2A0AF.1080300@ens-lyon.org> <87prfx6xsc.fsf@frosties.localdomain> <49D35307.4000502@ens-lyon.org> Date: Wed, 01 Apr 2009 17:57:28 +0200 In-Reply-To: <49D35307.4000502@ens-lyon.org> (Martin Jambon's message of "Wed, 01 Apr 2009 13:41:59 +0200") Message-ID: <87wsa49xjr.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: V01U2FsdGVkX19gmdv9A5h8rsxKY6WO7/Mc2nu7P8AwMTu1dfJ4 PnADHeO3usyZQMrINALM1Oij9iZQGZy5sjZ/TML3MpINN35K5h BkoZ38TUA= X-Spam: no; 0.00; bug:01 ens-lyon:01 mutable:01 superset:01 ocaml:01 sig:01 val:01 val:01 iter:01 struct:01 mutable:01 prev:01 prev:01 iter:01 printf:01 Martin Jambon writes: > Would the following work for you: No. Not just like this. > type 'a linked = { > data : 'a; > mutable next : < > linked option > } > (* constraint 'a = < .. > *) > > let create data next = { > data = data; > next = (next :> < > linked option) > } > > let set_next x y = > x.next <- (y :> < > linked option) > > > class s = > object > method s = "abc" > end > > class i = > object > method i = 123 > end class s and i have no access to the linked type. You could not remove a class s or i from the linked structure in O(1) from within class s or i. So linked would have to handle any function that might require altering the linked structure and pass parts of it to its data. But data is an unknown type so no method of it can be called. I would first need a class type containing the common functionality. Then 'a needs to be constraint to a superset of that class and next has to be an linked option of that class. Only then can the linked type call methods of its data. Your suggestion has one benefit though. By using a record + normal functions instead of a class one avoids a recursively constraint method, which ocaml doesn't like. MfG Goswin ---------------------------------------------------------------------- PS: below is a completly object free solution. It comes at the cost of requireing Obj.magic though. But its evilness is contained in M alone and can't escape. Not sure yet what way I will go. module M : sig type 'a fn = { to_string : 'a -> string; alter : 'a -> 'a } type 'a base val make : 'a -> 'a fn -> 'a base val to_string : 'a base -> string val alter : 'a base -> unit val iter : ('a base -> unit) -> unit end = struct type 'a fn = { to_string : 'a -> string; alter : 'a -> 'a } type 'a base = { mutable next : unit base; mutable prev : unit base; mutable data : 'a; fn : 'a fn } let unit_fn = { to_string = (fun () -> ""); alter = (fun () -> ()) } let rec head = { next = head; prev = head; data = (); fn = unit_fn } let make data fn = let e = { next = head; prev = head.prev; data = data; fn = fn } in head.prev.next <- Obj.magic e; head.prev <- Obj.magic e; e let to_string x = x.fn.to_string x.data let alter x = x.data <- x.fn.alter x.data let iter (fn : 'a base -> unit) = let fn : unit base -> unit = Obj.magic fn in let rec loop = function x when x == head -> () | x -> fn x; loop x.next in loop head.next end let string_fn = { M.to_string = (fun s -> s); M.alter = (fun s -> s ^ "+") } let int_fn = { M.to_string = (fun i -> Printf.sprintf "%d" i); M.alter = (fun i -> i +1) } let s = M.make "s" string_fn let i = M.make 1 int_fn let _ = M.iter (fun x -> Printf.printf "%s\n" (M.to_string x)) let _ = M.iter M.alter let _ = M.iter (fun x -> Printf.printf "%s\n" (M.to_string x)) => s 1 s+ 2