caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] value restriction and records' rank-2 polymorphism
@ 2011-06-21  7:13 Dmitry Grebeniuk
  2011-06-21  8:31 ` Jacques Garrigue
  0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Grebeniuk @ 2011-06-21  7:13 UTC (permalink / raw)
  To: caml-list

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 mkpair1 from_string =
  (* some common values here *)
  ( fun s f -> try f (from_string s) with [e -> failwith "mkpair1"]
  , fun s f -> try f (Some (from_string s)) with [e -> f None]
  );
value mkpair1 :
  ('a -> 'b) -> ('a -> ('b -> 'c) -> 'c * 'a -> (option 'b -> 'd) -> 'd) = <fun>
# value identity x = x;
value identity : 'a -> 'a = <fun>
# value (id11, id12) = mkpair1 identity;
value id11 : '_a -> ('_a -> '_b) -> '_b = <fun>
value id12 : '_a -> (option '_a -> '_b) -> '_b = <fun>

  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 = <fun>
# value { notnull = id21 ; nullable = id22 } = mkpair2 identity;
value id21 : func string 'a = <fun>
value id22 : func (option string) 'a = <fun>
#

  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?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] value restriction and records' rank-2 polymorphism
  2011-06-21  7:13 [Caml-list] value restriction and records' rank-2 polymorphism Dmitry Grebeniuk
@ 2011-06-21  8:31 ` Jacques Garrigue
  2011-06-21  8:55   ` Dmitry Grebeniuk
  0 siblings, 1 reply; 3+ messages in thread
From: Jacques Garrigue @ 2011-06-21  8:31 UTC (permalink / raw)
  To: Dmitry Grebeniuk; +Cc: caml-list


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 = <fun>
[...]
>  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 = <fun>
> # value { notnull = id21 ; nullable = id22 } = mkpair2 identity;
> value id21 : func string 'a = <fun>
> value id22 : func (option string) 'a = <fun>
> #
> 
>  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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Caml-list] value restriction and records' rank-2 polymorphism
  2011-06-21  8:31 ` Jacques Garrigue
@ 2011-06-21  8:55   ` Dmitry Grebeniuk
  0 siblings, 0 replies; 3+ messages in thread
From: Dmitry Grebeniuk @ 2011-06-21  8:55 UTC (permalink / raw)
  To: Jacques Garrigue

Hello, Jacques.

  Thanks for reply!  I'll use records for <3.12 without any fear of
future changes, and will use your nice solution with first-class
modules when I'll have >=3.12 everywhere I need to compile
my code on.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-06-21  9:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-21  7:13 [Caml-list] value restriction and records' rank-2 polymorphism Dmitry Grebeniuk
2011-06-21  8:31 ` Jacques Garrigue
2011-06-21  8:55   ` Dmitry Grebeniuk

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).