Apologies for posting such long, non-compilable code. But despite reading several questions and answers on stackoverflow on ocaml's functors, I don't get how to solve this:
Assume I have a very abstract data structure:
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
Based on this, I can make concrete data structures on these abstract implementation by passing a functor. For example I made:
concrete_ads.mli
module Make (Entry: Ads.ENTRY) : (ads.T with type entry = Entry.t)
This work, I can now use my implementation in other source-files, for example like this:
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);;
And, then, use the implemenation like:
let at = AT.create () in
let ati = AT.insert (1,2) at in
let atd = AT.delete (1,2) ati in
... etc.
Now, I want write several functions that operate on these data structures in a seperate sourcefile, and they should be accesible from outside. But, I do not know how to declare the type of these functions. Something like this:
search.mli
val search : Int -> Ads.T -> int list
But, when compiling I get:
Failure: "invalid long identifier type"
I, then, thought I need to specifically declare the module of adt as a
submodule in search.mli, something like:
search.mli
module AD = Ads;;
...
val search : Int -> AD.T -> int list
But, I get:
Parse error: [module_declaration] expected after [a_UIDENT] (in [sig_item])
What am I missing here ? I feel I either fail with the syntax, or did not fully grasp the concept of Functors, Modules and Submodules ...
Edit Thank you so much for your explanation, gasche! With your example I was able to write what I inteded. I'll post it here for clarification, since there seems to be alot of confusion about functors in ocaml.
In fact I wanted to make the function abstract with respect to Ads.T, but require a specific type for Ads.T.t.
I now have search.mli:
module Make (T : Ads.T with type entry = int * int) : sig
val search : T.t -> int -> int
end;;
And, in 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;;
And it worked exactly as I intended.