我有两个文件:myUnionFind.ml
和myUnionFind_test.ml
。这两个文件都在same directory
。
open Batteries
module type MyUnionFindSig =
sig
type union_find
val print_array : 'a array -> unit
val create_union : int -> union_find
val union_weighted : union_find -> int -> int -> unit
val is_connected_weighted : union_find -> int -> int -> bool
end;;
module MyUnionFind : MyUnionFindSig =
struct
let print_array ary = print_endline (BatPervasives.dump ary);;
type union_find = {id_ary : int array; sz_ary : int array};;
let create_union n = {id_ary = Array.init n (fun i -> i);
sz_ary = Array.make n 1};;
(* weighted quick union find *)
let find_root ary i =
let rec find j =
if ary.(j) = j then j
else find ary.(j)
in
find i;;
let union_weighted {id_ary;sz_ary} p q =
let root_p = find_root id_ary p in
let root_q = find_root id_ary q in
if sz_ary.(root_p) < sz_ary.(root_q) then begin
id_ary.(root_p) <- id_ary.(root_q);
sz_ary.(root_q) <- sz_ary.(root_q) + sz_ary.(root_p)
end
else begin
id_ary.(root_q) <- id_ary.(root_p);
sz_ary.(root_p) <- sz_ary.(root_p) + sz_ary.(root_q)
end;;
let is_connected_weighted {id_ary;_} p q = (find_root id_ary p) = (find_root id_ary q);;
end
open Batteries
let uf2 = MyUnionFind.create_union 10;;
MyUnionFind.union_weighted uf2 0 3;;
MyUnionFind.union_weighted uf2 1 4;;
MyUnionFind.union_weighted uf2 4 3;;
MyUnionFind.union_weighted uf2 2 8;;
MyUnionFind.print_array uf2.MyUnionFind.id_ary;;
BatPervasives.print_bool (MyUnionFind.is_connected_weighted uf2 0 3);;
我试过
ocamlfind ocamlc -package batteries -c myUnionFind.ml
。它奏效了,我可以看到myUnionFind.cmi
和myUnionFind.cmo
。
然后我尝试通过
编译myUnionFind_test.ml
ocamlfind ocamlc -package batteries -c myUnionFind_test.ml
。
它给出了这个错误:
文件“myUnionFind_test.ml”,第3行,字符10-34:错误:未绑定 值MyUnionFind.create_union
我无法弄清楚原因。我在模块create_union
中定义了MyUnionFind
,但为什么找不到它?
答案 0 :(得分:3)
您在模块中定义模块(myUnionFind.ml是一个模块)。
所以在你的测试文件中,你必须像这样打开你的模块:
open Batteries
open MyUnionFind (* Here !*)
let uf2 = MyUnionFind.create_union 10;;
MyUnionFind.union_weighted uf2 0 3;;
MyUnionFind.union_weighted uf2 1 4;;
MyUnionFind.union_weighted uf2 4 3;;
MyUnionFind.union_weighted uf2 2 8;;
MyUnionFind.print_array uf2.MyUnionFind.id_ary;;
BatPervasives.print_bool (MyUnionFind.is_connected_weighted uf2 0 3);;
或为每个调用添加前缀,如:
let uf2 = MyUnionFind.MyUnionFind.create_union 10;;
如果你只是在myUnionFind.ml中定义一个模块而你不想像以前那样有两个模块,你可以像这样创建一个.ml和.mli文件:
(* myUnionFind.mli *)
type union_find = {id_ary : int array; sz_ary : int array}
val print_array : 'a array -> unit
val create_union : int -> union_find
val union_weighted : union_find -> int -> int -> unit
val is_connected_weighted : union_find -> int -> int -> bool
(* myUnionFind.ml *)
type union_find = {id_ary : int array; sz_ary : int array};;
let print_array ary = (* ... *)
let create_union n = (* ... *)
let union_weighted r p q = (* ... *)
let find_root ary i = (* ... *)
请注意,如果您引用id_ary
字段,则必须将其放入模块签名
答案 1 :(得分:1)
OCaml为每个文件免费提供一个级别的模块。所以你的myUnionFind.ml
在这个免费模块中有一个模块。要避免这种情况,请在文件的顶层声明所有内容。然后你只有一个模块,名称与文件相同。