* [Caml-list] Function not polymorphic enough @ 2014-12-19 13:30 Maxence Guesdon 2014-12-19 15:33 ` Gabriel Scherer 0 siblings, 1 reply; 3+ messages in thread From: Maxence Guesdon @ 2014-12-19 13:30 UTC (permalink / raw) To: caml-list 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 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Caml-list] Function not polymorphic enough 2014-12-19 13:30 [Caml-list] Function not polymorphic enough Maxence Guesdon @ 2014-12-19 15:33 ` Gabriel Scherer 2014-12-19 18:58 ` Maxence Guesdon 0 siblings, 1 reply; 3+ messages in thread From: Gabriel Scherer @ 2014-12-19 15:33 UTC (permalink / raw) To: Maxence Guesdon; +Cc: caml-list 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 = <fun> val extend : (t -> t) -> unit = <fun> 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 = <fun>} val extend : (t -> t) -> unit = <fun> On Fri, Dec 19, 2014 at 2:30 PM, Maxence Guesdon <Maxence.Guesdon@inria.fr> 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 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Caml-list] Function not polymorphic enough 2014-12-19 15:33 ` Gabriel Scherer @ 2014-12-19 18:58 ` Maxence Guesdon 0 siblings, 0 replies; 3+ messages in thread From: Maxence Guesdon @ 2014-12-19 18:58 UTC (permalink / raw) To: Gabriel Scherer; +Cc: caml-list On Fri, 19 Dec 2014 16:33:12 +0100 Gabriel Scherer <gabriel.scherer@gmail.com> 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 = <fun> > val extend : (t -> t) -> unit = <fun> > > 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 = <fun>} > val extend : (t -> t) -> unit = <fun> 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 > <Maxence.Guesdon@inria.fr> 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 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-12-19 18:58 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-12-19 13:30 [Caml-list] Function not polymorphic enough Maxence Guesdon 2014-12-19 15:33 ` Gabriel Scherer 2014-12-19 18:58 ` Maxence Guesdon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox