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 p5L8W2aN011915 for ; Tue, 21 Jun 2011 10:32:05 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ar4DAKZWAE7RVaA2kGdsb2JhbAA+AQMFDZtbiwoIFAEBAQEJCQ0HFAQhiHOiV48EhGuJHwEBAwaDGIMMBIcgikaFfoV9PIE6giQ X-IronPort-AV: E=Sophos;i="4.65,400,1304287200"; d="scan'208";a="111592306" Received: from mail-pw0-f54.google.com ([209.85.160.54]) by mail1-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 21 Jun 2011 10:32:04 +0200 Received: by pwi7 with SMTP id 7so395415pwi.27 for ; Tue, 21 Jun 2011 01:32:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:subject:mime-version:content-type:from :in-reply-to:date:cc:content-transfer-encoding:message-id:references :to:x-mailer; bh=dQyWsw4Ac4n7IDFxGhRmANX0Vn/rn/SmNzY+Sq1ua3I=; b=hu02E0+77SYkul08y4r/rry+dADHX1bcll8y2SKHZ3/7+HO7PYI6fGnD2DiEkyfBmi ohjn6WVlDbazB9Lmuc+UVT2+Vox0LuT5Dd721/jYco8dXOL4SlwWPzaNtbbR5NmlzNT7 h+jmknc3SI46mb9pEG6sjeHFr6UEnAXp9yUxk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:subject:mime-version:content-type:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to:x-mailer; b=mRxPIGAwILB6377fLRsPrlxTd2cEwx7BypedoF3viG7qbBK3fJUSDaTLoKMknRwS5t VIbwsmvpd1+vt3s6SloYmR+NygzRtIzwC1Ofs8O5ihI7SMsY5MR/Da9WF1Wpje4DUB6N /W6MwsbGXQjQLAE0tNXhPubx+uw97x2Sl7BIo= Received: by 10.68.20.137 with SMTP id n9mr2575942pbe.121.1308645122424; Tue, 21 Jun 2011 01:32:02 -0700 (PDT) Received: from tet.garrigue.jp (58x158x128x157.ap58.ftth.ucom.ne.jp [58.158.128.157]) by mx.google.com with ESMTPS id m9sm3603568pbd.39.2011.06.21.01.31.59 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 21 Jun 2011 01:32:01 -0700 (PDT) Sender: Jacques Garrigue Mime-Version: 1.0 (Apple Message framework v1084) Content-Type: text/plain; charset=us-ascii From: Jacques Garrigue In-Reply-To: Date: Tue, 21 Jun 2011 17:31:57 +0900 Cc: caml-list@inria.fr Message-Id: References: To: Dmitry Grebeniuk X-Mailer: Apple Mail (2.1084) Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by walapai.inria.fr id p5L8W2aN011915 Subject: Re: [Caml-list] value restriction and records' rank-2 polymorphism On 2011/06/21, at 16:13, Dmitry Grebeniuk wrote: > Hello. > > I need to create two functions that share common state, and I want to > create this common state once per program run, and I want to make each > function call very cheap. When I'm doing it naively, I get "value restriction": > > $ ocaml > # #use "topfind";; > # #camlp4r;; > # type func 'a 'r = string -> ('a -> 'r) -> 'r; > type func 'a 'b = string -> ('a -> 'b) -> 'b > # value identity x = x; > value identity : 'a -> 'a = [...] > But I've found a trick that uses rank-2 polymorphism of record fields: > > # type pair 'a 'b = > { notnull : !'r . func 'a 'r > ; nullable : !'r . func (option 'a) 'r > }; > type pair 'a 'b = > { notnull : !'c. func 'a 'c; nullable : !'d. func (option 'a) 'd } > # value mkpair2 from_string = > (* some common values here *) > { notnull = fun s f -> try f (from_string s) with [e -> failwith "mkpair2"] > ; nullable = fun s f -> try f (Some (from_string s)) with [e -> f None] > }; > value mkpair2 : (string -> 'a) -> pair 'a 'b = > # value { notnull = id21 ; nullable = id22 } = mkpair2 identity; > value id21 : func string 'a = > value id22 : func (option string) 'a = > # > > And everything seems to work: the record is created once, then > it is "decomposed" to id21 and id22 functions (either right after its > creation or on each call, it should be cheap anyway). But I don't > know whether this solution is correct and will it remain correct in > future versions of OCaml -- can you help me here? I'm not sure I understand the details of all you are trying do, but there is no plan to remove polymorphic record fields from the language, so you can use this feature safely. (Strictly speaking, this is a language extension, so there may be some changes in the future, but there is nothing planned) Since 3.12, an alternative approach which should be just as cheap is to use a first class module. This is a bit more verbose. module type Pair = sig type t val notnull : (t,'r) func val nullable : (t option, 'r) func end let mkpair (type a) from_string = (module struct type t = a let notnull s f = try f (from_string s) with e -> failwith "mkpair" let nullable s f = try f (Some (from_string s)) with e -> f None end : Pair with type t = a) module M = (val (mkpair (fun x -> x)) : Pair with type t = string) let id31 = M.notnull let id32 = M.nullable Jacques Garrigue