Модуль 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.