Извините за публикацию такого длинного не компилируемого кода.Но, несмотря на то, что я прочитал несколько вопросов и ответов о стековом потоке на функторах 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"
Я тогда подумал, что нужно специально объявить модульadt как подмодуль в search.mli
, что-то вроде:
search.mli
module AD = Ads;;
...
val search : Int -> AD.T -> int list
Но я получаю:
Parse error: [module_declaration] expected after [a_UIDENT] (in [sig_item])
Чего мне здесь не хватает?Я чувствую, что либо ошибаюсь с синтаксисом, либо не полностью понял концепцию функторов, модулей и подмодулей ...
Edit Большое спасибо за ваше объяснение, gasche!На вашем примере я смог написать то, что я имел в виду.Я опубликую это здесь для пояснения, так как, кажется, в ocaml много путаницы с функторами.
На самом деле я хотел сделать функцию абстрактной по отношению к 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;;
И все работает именно так, как я и предполагал.