From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 789997FAE1 for ; Fri, 19 Dec 2014 19:58:25 +0100 (CET) X-IronPort-AV: E=Sophos;i="5.07,608,1413237600"; d="scan'208";a="114231755" Received: from adijon-652-1-21-106.w86-204.abo.wanadoo.fr (HELO alcazar2) ([86.204.12.106]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 19 Dec 2014 19:58:24 +0100 Date: Fri, 19 Dec 2014 19:58:21 +0100 From: Maxence Guesdon To: Gabriel Scherer Cc: "caml-list@inria.fr" Message-ID: <20141219195821.595b062d@alcazar2> In-Reply-To: References: <20141219143039.425107b3@alcazar2> Organization: INRIA X-Mailer: Claws Mail 3.9.3 (GTK+ 2.24.23; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Subject: Re: [Caml-list] Function not polymorphic enough On Fri, 19 Dec 2014 16:33:12 +0100 Gabriel Scherer wrote: > My understanding of the issue is that the type of "extend" cannot be > specified without first-class polymorphism (talking about argument > types that are polymorphic, instead of prenex polymorphism at the very > beginning of the function type). extend should take a function of type > ('a . ('a -> unit) -> 'a list) -> unit). To do that in OCaml, you > should explicitly take a first-class polymorphic argument (this cannot > be inferred), namely a record or object that has a polymorphic > field/method. Using the polymorphic record approach, this means you > need a definition > > type t = {poly : 'a . ('a -> unit) -> 'a list -> unit} > > that is *not* local to your definition, so that users of "extend" can > talk about it. (You could use an object type if you want a structural > rather than nominal type here.) > > Using this idea, there is actually no need to define a type locally, a > simple reference on my t will do, which gives the following: > > # let (fn, extend) = > let v = ref { poly = fun _f _li -> assert false } in > let fn f li = !v.poly f li in > let extend g = v := g !v in > (fn, extend);; > val fn : ('_a -> unit) -> '_a list -> unit = > val extend : (t -> t) -> unit = > > If you want to non-polymorphic variables to go away, you can reveal > that "fn" is really a t: > > # let (fn, extend) = > let v = ref { poly = fun _f _li -> assert false } in > let fn = { poly = fun f li -> !v.poly f li } in > let extend g = v := g !v in > (fn, extend);; > val fn : t = {poly = } > val extend : (t -> t) -> unit = Thanks for your explanation. Sadly, I wanted to keep the type machinery hidden :-( - m > > > On Fri, Dec 19, 2014 at 2:30 PM, Maxence Guesdon > wrote: > > Hello, > > > > With the following code: > > > > let (fn, extend) = > > let module M = struct > > type t = { mutable f : 'a. ('a -> unit) -> 'a list -> unit } > > let v = > > { f = fun (type a) -> fun (poly_a : a -> unit) -> fun _ -> > > assert false > > } > > end in > > let fn = fun f x -> M.v.M.f x in > > let extend g = M.v.M.f <- g M.v.M.f in > > (fn, extend) > > > > I get the following message about " g M.v.M.f": > > Error: This field value has type ('b -> unit) -> 'b list -> unit > > which is less general than 'a. ('a -> unit) -> 'a list -> unit > > > > Does anyone know how to make "g M.v.M.f" general enough ? > > > > Regards, > > > > Maxence > > > > -- > > Caml-list mailing list. Subscription management and archives: > > https://sympa.inria.fr/sympa/arc/caml-list > > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > Bug reports: http://caml.inria.fr/bin/caml-bugs