这个 OCaml 代码是如何工作的?
How does this OCaml code work?
以下 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 ()
的调用创建了一个二元组函数。元组中的第一个函数在封闭的引用单元中存储一个任意值;第二个函数检索它。如果将类型 t 的错误值提供给第二个函数,则它 returns None
代替。但是,在我看来,这会导致清除引用单元格,从而进一步尝试检索失败的值,但这并没有发生。另外,我一般不明白将错误的值传递给投影函数 get 时会发生什么。
当调用 embed
时,为函数 put
和 get
分配一个新的引用 r
和两个新的闭包。当某些 put
被调用时,它 return 是一个新函数(我们称它为 setter),它的闭包中也有 r
。
如果 setter 被赋予相应的 get
,那么在两个闭包中捕获的 r
是相同的,因此当 get
调用f true
,它修改 get
闭包中的 r
,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
捕获,setter不一样。 (我们称它们为 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
将 return None
。
以下 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 ()
的调用创建了一个二元组函数。元组中的第一个函数在封闭的引用单元中存储一个任意值;第二个函数检索它。如果将类型 t 的错误值提供给第二个函数,则它 returns None
代替。但是,在我看来,这会导致清除引用单元格,从而进一步尝试检索失败的值,但这并没有发生。另外,我一般不明白将错误的值传递给投影函数 get 时会发生什么。
当调用 embed
时,为函数 put
和 get
分配一个新的引用 r
和两个新的闭包。当某些 put
被调用时,它 return 是一个新函数(我们称它为 setter),它的闭包中也有 r
。
如果 setter 被赋予相应的
get
,那么在两个闭包中捕获的r
是相同的,因此当get
调用f true
,它修改get
闭包中的r
,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
捕获,setter不一样。 (我们称它们为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
将 returnNone
。