Модуль OCaml: включить и открыть?
Я новичок в OCaml Module, и мне не удалось использовать свой собственный модуль, не объединяя "include" и "open".
Я попытался поместить подпись в отдельный файл .mli без успеха.
Ниже показан минимальный (не) рабочий пример, который я пытаюсь скомпилировать с помощью
ocamlc -o main Robot.ml main.ml
Что мне нужно сделать, чтобы использовать только "open" или только "include", но не оба из них?
Файл "Robot.ml":
module type RobotSignature =
sig
val top: unit -> unit
end
module Robot =
struct
let top () =
begin
Printf.printf "top\n"
end
(* Should not be visible from the 'main' *)
let dummy () =
begin
Printf.printf "dummy\n"
end
end
Файл "main.ml" (не работает):
open Robot;;
top();
Файл "main.ml" (рабочий):
include Robot;;
open Robot;;
top();
Ответы
Ответ 1
У вас есть два уровня робота. Поскольку вы явно называете свой модуль "Робот" в файле robot.ml, вам нужно будет открыть Robot, а затем вызвать Robot.top(). Все, что содержится в файле robot.ml, уже неявно помещается внутри модуля Robot.
Вы можете избавиться от дополнительной декларации модуля Robot в robot.ml.
robot.ml станет:
module type RobotSignature =
sig
val top: unit -> unit
end
let top () =
begin
Printf.printf "top\n"
end
Затем он должен работать так же, как и у вас в main.ml.
Обновление, основанное на комментарии ниже: Если вы обеспокоены тем, что все в robot.ml теперь будет видимым при открытии Robot, вы можете определить файл robot.mli, который определяет функции, доступные снаружи. Например, скажем, вы добавили функцию robot.ml: помощник:
let top () =
begin
Printf.printf "top\n"
end
let helper () =
Printf.printf "helper\n"
... и затем вы определяете свой robot.mli следующим образом:
val top: unit -> unit
Затем скажем, вы пытаетесь вызвать помощника из main.ml:
open Robot;;
top();
(* helper will not be visible here and you'll get a compile error*)
helper ()
Затем, когда вы пытаетесь скомпилировать, вы получите сообщение об ошибке:
$ ocamlc -o main robot.mli robot.ml main.ml
File "main.ml", line 4, characters 0-6:
Error: Unbound value helper
Ответ 2
У вас есть два способа сделать это:
-
Во-первых, вы можете ограничить вашу подструктуру правильной сигнатурой:
module Robot : RobotSignature = struct ... end
Затем в main.ml
вы можете сделать open Robot.Robot
: первый Robot
означает блок компиляции, связанный с robot.ml
, второй Robot
- это подмодуль, который вы определили внутри robot.ml
-
Вы также можете удалить один уровень и создать robot.mli
, содержащий:
val top: unit -> unit
и robot.ml
, содержащие:
let top () =
Printf.printf "top\n"
(* Should not be visible from the 'main' *)
let dummy () =
Printf.printf "dummy\n"
Вы можете скомпилировать модули с помощью ocamlc -c robot.mli && ocamlc -c robot.ml
, а затем в main.ml
просто использовать open Robot
.