Strange module loading issue in OCaml

折月煮酒 提交于 2019-12-20 03:52:50

问题


I have two files: myUnionFind.ml and myUnionFind_test.ml. Both files are in the same directory.

myUnionFind.ml

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

myUnionFind_test.ml

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);;

I tried

ocamlfind ocamlc -package batteries -c myUnionFind.ml. It worked, I can see myUnionFind.cmi and myUnionFind.cmo.

Then I tried to compile myUnionFind_test.ml via

ocamlfind ocamlc -package batteries -c myUnionFind_test.ml.

It gives this error:

File "myUnionFind_test.ml", line 3, characters 10-34: Error: Unbound value MyUnionFind.create_union


I can't figure out why. I have defined create_union in module MyUnionFind, but why it can't be found?


回答1:


You define a module in a module (your myUnionFind.ml is a module).

So in your test file, you have to open your module like this:

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);;

or prefix each call like:

let uf2 = MyUnionFind.MyUnionFind.create_union 10;;

If you just define a module in myUnionFind.ml and you don't want to have two modules like previously, you can just create a .ml and .mli file like this:

 (* 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 = (* ... *)

Be careful, if you have a reference to id_ary field, you have to put it in the module signature




回答2:


OCaml gives you one level of module for free with each file. So your myUnionFind.ml has a module within this free module. To avoid this, declare everything at the top level of the file. Then you have just one module, with the same name as the file.



来源:https://stackoverflow.com/questions/14876228/strange-module-loading-issue-in-ocaml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!