OCaml中奇怪的模块加载问题 [英] Strange module loading issue in OCaml

查看:109
本文介绍了OCaml中奇怪的模块加载问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个文件: myUnionFind.ml myUnionFind_test.ml 。这两个文件都位于同一目录中



myUnionFind.ml



 打开电池

模块类型MyUnionFindSig =
sig

类型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} ;;

(*加权快速联盟查找*)

让find_root ary i =
让rec找到j =
if ary。(j)= j然后j
找到ary。(j)
in
找到i ;;

让union_weighted {id_ary; sz_ary} pq =
let root_p = find_root id_ary p in
let root_q = find_root id_ary q in
如果sz_ary。(root_p)< ; sz_ary。(root_q)然后开始
id_ary。(root_p)< - id_ary。(root_q); (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



 打开电池

让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



然后我试着通过

ocamlfind ocamlc来编译 myUnionFind_test.ml - 包装电池-c myUnionFind_test.ml



出现此错误:


文件myUnionFind_test.ml,第3行,字符10-34:错误:未绑定
值MyUnionFind.create_union







我找不出原因。我在模块 MyUnionFind 中定义了 create_union ,但为什么找不到它?

解决方案

您在一个模块中定义一个模块(您的myUnionFind.ml是一个模块)。
$ b $所以在你的测试文件中,你必须像这样打开你的模块:

 打开电池
打开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 *)
类型union_find = {id_ary:int数组; 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 *)
类型union_find = {id_ary:int array; sz_ary:int array} ;;

让print_array ary =(* ... *)
让create_union n =(* ... *)
let union_weighted rpq =(* ... *)
让find_root ary i =(* ... *)

小心,如果您有 id_ary 字段的引用,则必须将其放入模块签名中


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?

解决方案

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

这篇关于OCaml中奇怪的模块加载问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆