以下OCaml代码创建了一个通用类型(不是我的,来自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
创建通用类型。在其中,对embed ()
的调用会创建一个2元组的函数。元组中的第一个函数在封闭的ref单元格中存储任意值;第二个函数检索它。如果第二个函数给出了类型为t的错误值,则返回None
。但是,在我看来,这将导致ref单元被清除,因此进一步尝试检索值失败,这不会发生。另外,我一般不了解将错误值传递给投影函数get时会发生什么。
答案 0 :(得分:7)
调用embed
后,系统会为r
和put
分配新的参考get
和两个新的闭包。当一些put
被调用时,它返回一个新函数(让我们称之为setter),它的闭包中也有r
。
如果该setter被赋予相应的get
,则两个闭包中捕获的r
都是相同的,因此当get
调用f true
时,它会修改r
关闭get
,let res = !r
读取Some
值。
let get f =
f true; (* assign the shared reference r *)
let res = !r in (* read r *)
f false; (* clear r *)
res
如果将setter指定给非对应的get
,则r
捕获的get
与设置者不同。 (我们称之为r1
和r2
)
let get f =
f true; (* assign r1 *)
let res = !r in (* read r2 *)
f false; (* clear r1 *)
res
由于get需要始终清除r
,因此我们知道在调用之前
get
,r2
为None
。因此get
将返回None
。