在一个模块中,我定义了一个表示图形节点的类型,它具有多态数据字段,即
type 'a t = {data: 'a; adj: 'a t list}
如何创建Set这些数据?我尝试了以下内容(根据其中一条建议here。
let cmp (g1:int Graph.t) (g2: int Graph.t) : int=
if phys_equal g1 g2 then
0
else
Int.compare g1.data g2.data
let make_set () =
let module Ord=struct
type t=int Graph.t
let compare=cmp
end
in (module Set.Make(Ord): Set.S with type elt=Ord.t)
但是,当我这样做时,我得到“由'带有'的签名没有名为elt的组件”
答案 0 :(得分:1)
我不确定你要做什么,但如果你只想制作数据类型为int
的节点集,你不需要使用比通常的OCaml更高级的东西。模块操作。
以下代码适用于我:
module Graph =
struct
type 'a t = {data: 'a; adj: 'a t list}
end
let cmp (g1:int Graph.t) (g2: int Graph.t) : int =
if g1 == g2 then
0
else
compare g1.Graph.data g2.Graph.data
module GSet = Set.Make(struct type t = int Graph.t let compare = cmp end)
这是一段代码会话:
$ ocaml
OCaml version 4.01.0
# #use "g.ml";;
module Graph : sig type 'a t = { data : 'a; adj : 'a t list; } end
val cmp : int Graph.t -> int Graph.t -> int = <fun>
module GSet :
sig
type elt = int Graph.t
. . .
end
# let myset = GSet.add { Graph.data = 14; adj = [] } GSet.empty;;
val myset : GSet.t = <abstr>
# GSet.is_empty myset;;
- : bool = false
我没有理由限制模块类型,因为Set.S
已经是Set.Make
返回的模块类型。但我不是OCaml模块类型的复杂用户。
答案 1 :(得分:1)
对于我来说,该代码在解释器中工作正常。也许您在Set
中未定义elt
类型的情况下打开了另一个S
模块?
如果我在解释器中定义以下Set
:
# module Set = struct
module type S = sig end
end;;
module Set : sig module type S = sig end end
然后在编写时简单地重新定义make_set
,我实际上得到了相同的错误消息。在使用解释器尝试代码时,请始终牢记您可能正在使用之前编写的定义。
根据经验,尽量避免将值绑定到您希望使用的库中已使用的名称(我知道在那里缩短您的名字很有吸引力,但至少要添加一个小的独特前缀 - 例如,在您的情况下使用ISet
而不是Set
。
您始终可以将代码作为脚本运行,即从命令行启动它,如下所示:
$ ocaml my_script.ml
或者通过解释器提示符处的#use
指令。这使您可以在使用新的ocaml环境测试代码片段之前编写代码片段。
最后,正如@ Jeffrey提供的答案一样,一个解压缩的模块足以满足大多数用途;你的代码是关于实例化一个第一类模块,如果你打算在不使用仿函数的情况下传递该模块,那么这只是有趣的。有关进一步说明,请参阅documentation模块(以及该语言的相关extensions)。