caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [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;
as well as URLs for NNTP newsgroup(s).