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=1.7 required=5.0 tests=AWL,NO_REAL_NAME,SPF_FAIL autolearn=disabled version=3.1.3 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 8E013BC6B for ; Sat, 15 Dec 2007 13:11:13 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAACNTY0fAXQImh2dsb2JhbACPDHYCAQgKKZg3 X-IronPort-AV: E=Sophos;i="4.24,171,1196636400"; d="scan'208";a="6859940" Received: from discorde.inria.fr ([192.93.2.38]) by mail3-smtp-sop.national.inria.fr with ESMTP; 15 Dec 2007 13:11:13 +0100 Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id lBFCBCAc025384 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Sat, 15 Dec 2007 13:11:13 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ah4FAL5SY0fAEKcgYGdsb2JhbACPDGkDFQQDLJg2 X-IronPort-AV: E=Sophos;i="4.24,171,1196636400"; d="scan'208";a="5233751" Received: from selenite.metnet.navy.mil ([192.16.167.32]) by mail2-smtp-roc.national.inria.fr with ESMTP; 15 Dec 2007 13:11:12 +0100 Received: (qmail 28007 invoked by uid 107); 15 Dec 2007 12:10:59 -0000 Received: from unknown (HELO Adric.metnet.fnmoc.navy.mil) (10.100.105.152) by selenite.metnet.navy.mil with SMTP; 15 Dec 2007 12:10:59 -0000 Received: by Adric.metnet.fnmoc.navy.mil (Postfix, from userid 760) id 4A826AF01; Sat, 15 Dec 2007 04:08:55 -0800 (PST) From: oleg@okmij.org To: pedagand@gmail.com, caml-list@inria.fr Subject: Re: "Ref" and copy of functions Reply-To: oleg@pobox.com Errors-To: oleg@okmij.org Message-Id: <20071215120855.4A826AF01@Adric.metnet.fnmoc.navy.mil> Date: Sat, 15 Dec 2007 04:08:55 -0800 (PST) X-Miltered: at discorde with ID 4763C460.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; oleg:01 mutable:01 trivial:01 val:01 val:01 lesson:98 20,:98 20,:98 rec:01 rec:01 functions:01 unsafe:01 int:01 int:01 output:02 If you like using the mutable state, perhaps you might find the following code helpful. The key idea is packaging the clone function along with the arrow. There is no longer any need in any unsafe features. The lesson from our tagless final APLAS paper is that many things are significantly easier if we do the work at the production site rather than at the consumption site. (* The first component is the arrow itself, the second one is the clone function*) type ('a,'b) arrow = {arrow: 'a -> 'b; clone: unit -> ('a,'b) arrow};; let rec arr f = {arrow = f; clone = fun () -> arr f};; let rec (>>>) f g = {arrow = (fun c -> g.arrow (f.arrow c)); clone = (fun () -> f.clone () >>> g.clone ())};; (* Here, our clone function uses the initial state rather than the current state. It is trivial to clone from the current state, if desired.*) let rec loop init f = let state = ref init in {arrow = (fun c -> let new_state , output = f.arrow ( !state , c ) in state := new_state; output); clone = (fun () -> loop init (f.clone ()))};; let arr_counter = loop 0 (arr (fun (counter, x) -> counter+1 ,counter+x));; let arr_double = arr (fun x -> 2*x);; let arr_my_small_arrow = arr_counter >>> arr_double;; let run f input = let v1 = f.arrow input in let v2 = f.arrow input in (v1,v2);; let test1 = run arr_my_small_arrow 10;; val test1 : int * int = (20, 22) let test2 = run arr_my_small_arrow 10;; val test2 : int * int = (24, 26) (*obviously, counter keeps counting *) let test3 = run (arr_my_small_arrow.clone ()) 10;; val test3 : int * int = (20, 22) (* cloning `resets' the counter *)