Модуль OCaml: включить и открыть? - PullRequest
11 голосов
/ 03 апреля 2012

Я довольно новичок в работе с модулем OCaml, и мне не удалось использовать свой собственный модуль, не объединив и «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();

Ответы [ 2 ]

12 голосов
/ 03 апреля 2012

У вас есть два уровня робота. Поскольку вы явно назвали свой модуль «Робот» в файле robot.ml, вам нужно открыть Robot, а затем вызвать Robot.top (). Все, что находится в файле robot.ml, уже неявно помещено в модуль Robot.

Вы можете избавиться от дополнительного объявления 'module 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, в котором указаны функции, которые доступно внешне. Например, допустим, вы добавили функцию с именем helper в 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
5 голосов
/ 03 апреля 2012

У вас есть два способа сделать это:

  • Сначала вы можете ограничить свою подструктуру правильной подписью:

    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.

...