很抱歉发了这么长的非可编译代码。尽管在stackoverflow上阅读了几个关于ocaml函数的问题和答案,但我仍然不知道如何解决这个问题:
假设我有一个非常抽象的数据结构:
ads.mli
module type ENTRY = sig
type t
val get_index : t -> int
val compare : t -> t -> int
end
module type T = sig
type entry
type t
val create : unit -> t
val insert : entry -> t -> t
val delete : entry -> t -> t
end
根据这个,我可以通过传递一个函数对象在这些抽象实现上创建具体的数据结构。例如我创建了:
concrete_ads.mli
module Make (Entry: Ads.ENTRY) : (ads.T with type entry = Entry.t)
现在,我可以在其他源文件中使用我的实现,例如像这样:
module AT = Concrete_ads.Make(
type t = int * int;;
let get_index = fst;;
let to_string = (fun (x,y) -> Printf "%i, %i" x y);;
end);;
然后,使用实现方式如下:
let at = AT.create () in
let ati = AT.insert (1,2) at in
let atd = AT.delete (1,2) ati in
现在,我想编写一些在这些数据结构上操作的函数,并将它们放在一个单独的源代码文件中以便外部访问。但是,我不知道如何声明这些函数的类型。应该像这样:
search.mli
val search : Int -> Ads.T -> int list
但是,在编译时我遇到了以下问题:
Failure: "invalid long identifier type"
我认为我需要在search.mli
中明确声明adt模块作为子模块,类似于:
search.mli
module AD = Ads;;
...
val search : Int -> AD.T -> int list
但是,我收到的是:
Parse error: [module_declaration] expected after [a_UIDENT] (in [sig_item])
我在这里缺少什么?我感觉我要么语法失败了,要么没有完全掌握函数对象、模块和子模块的概念... 编辑 非常感谢您的解释,gasche!通过您的示例,我能够写出自己想要的代码。由于ocaml中对functor的概念存在很多混淆,因此我将在此发布以进行澄清。
实际上,我想将该函数与
Ads.T
抽象化,但要求为Ads.T.t
指定特定类型。现在我有了
search.mli
:module Make (T : Ads.T with type entry = int * int) : sig
val search : T.t -> int -> int
end;;
而在 search.ml
中:
module Make (T : Ads.T with type entry = int * int) : sig
val search : T.t -> int -> int
end = struct
(* actual implementation of search *)
end;;
它完全按照我预期的方式起作用。