Reputation: 3611
The following OCaml code creates a universal type (not mine, from Jane Street's website):
module Univ : sig
type t
val embed: unit -> ('a -> t) * (t -> 'a option)
end = struct
type t = bool -> unit
let embed () =
let r = ref None in
let put x =
let sx = Some x in
fun b -> r := if b then sx else None
in
let get f =
f true;
let res = !r in
f false; res
in
put, get
end
creates a universal type. In it, a call to embed ()
creates a 2-tuple of functions. The first function in the tuple stores an arbitrary value in the closed-over ref cell; the second function retrieves it. If the wrong value of type t is given to the second function, it returns None
instead. However, it appears to me that this would cause the ref cell to be cleared and thus further attempts to retrieve the value to fail, which does not happen. Also, I do not understand in general what happens when passed a wrong value to the projection function get.
Upvotes: 2
Views: 162
Reputation: 1489
When embed
is called, a fresh reference r
and two fresh closures for the functions put
and get
are allocated. When some put
is called it returns a fresh function (let's call it the setter) that also has r
in its closure.
If that setter is given to the corresponding get
, the r
captured in both closure is the same, hence when get
calls f true
, it modifies the r
in get
closure, and let res = !r
read a Some
value.
let get f =
f true; (* assign the shared reference r *)
let res = !r in (* read r *)
f false; (* clear r *)
res
If the setter is given to a non-corresponding get
, the r
captured by get
and the setter is not the same. (let's call them r1
and r2
)
let get f =
f true; (* assign r1 *)
let res = !r in (* read r2 *)
f false; (* clear r1 *)
res
Since the get takes care of always clearing r
, we know that before calling
get
, r2
is None
. Hence get
will return None
.
Upvotes: 7