如何在 Ocaml 中将函数放入集合中?

Gly*_*ter 3 ocaml

我想制作一个包含函数的 Set 模块。但似乎没有办法比较 Set 需要的函数。这个看起来很明显的东西编译后:

module Action = struct
  type t = unit -> unit
  let compare : t -> t -> int = Stdlib.compare
end
module Actions = Set.Make(Action)
Run Code Online (Sandbox Code Playgroud)

但如果我尝试使用它:

Fatal error: exception Invalid_argument("compare: functional value")

我只是想比较这些函数是同一个对象,我不想做一些愚蠢的事情,比如比较它们的相同行为。

我应该在这里使用 Obj 模块中的东西吗?

Jef*_*eld 7

的语义Stdlib.compare是任意深入地观察对象内部,以了解它们的子部分如何进行比较。正如您所指出的,这对函数实际上不起作用。所以 OCaml 不允许compare应用于函数。

即使您愿意使用物理平等,也没有真正可以应用于函数的有用顺序。函数值是不可变的,并且可以由运行时系统物理复制或移动,至少在理论上是这样。

由于顺序必然是任意的,因此您可以通过制定自己的任意顺序来获得相同的效果:将函数与 int 值配对,该值在创建新对时单调增加。


ivg*_*ivg 6

为您的操作添加身份,例如,您可以按名称比较操作,

module Action = struct 

  type t = {
    name : string;
    func : (unit -> unit);
  }

  let compare x y = String.compare x.name y.name
 end
Run Code Online (Sandbox Code Playgroud)

您还应该确保所有操作具有不同的名称,例如通过引入记录所有创建的操作的全局哈希表。Action通过添加适当的签名,确保操作只能通过模块创建。