我想制作一个包含函数的 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 模块中的东西吗?
的语义Stdlib.compare
是任意深入地观察对象内部,以了解它们的子部分如何进行比较。正如您所指出的,这对函数实际上不起作用。所以 OCaml 不允许compare
应用于函数。
即使您愿意使用物理平等,也没有真正可以应用于函数的有用顺序。函数值是不可变的,并且可以由运行时系统物理复制或移动,至少在理论上是这样。
由于顺序必然是任意的,因此您可以通过制定自己的任意顺序来获得相同的效果:将函数与 int 值配对,该值在创建新对时单调增加。
为您的操作添加身份,例如,您可以按名称比较操作,
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
通过添加适当的签名,确保操作只能通过模块创建。