2012-04-03 3 views
10

Я довольно новичок в модуле OCaml, и мне не удалось использовать свой собственный модуль, не объединяя «включительно» и «открытую». Я попытался поставить подпись в отдельный файл .mli без успеха.OCaml Module: include AND open?

Ниже я указал минимум (не) работает пример, что я пытаюсь компилировать с

ocamlc -o main Robot.ml main.ml 

Что мне нужно сделать, чтобы только использовать «открыть» или только " включают ", но не оба из них?


Файл "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(); 
+0

Я думаю, у вас есть ответы на ваши вопросы. Вы также можете прочитать о [единицах компиляции] (http://caml.inria.fr/pub/docs/manual-ocaml/manual020.html). Но, пожалуйста, как только вы поняли, что делает 'open'. Не используйте его, это затрудняет понимание вашего кода. –

+0

Хорошо бы я согласился, но в этом случае цель состоит в том, чтобы предоставить простую «библиотеку роботов» для обучения базовому программированию новичкам (в частности, но не ограничиваясь OCaml). Поэтому я предпочитаю избегать синтаксиса Robot.top(), насколько это возможно. –

+0

Ну, я думаю, что это на самом деле сделает его более понятным для новичков, чтобы отобразить объект, который они действуют на явном. В любом случае, вы также можете посмотреть документацию по [open] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd170) и [включить] (http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd171). –

ответ

11

У вас есть два уровня робота. Поскольку вы явно называете свой модуль «Робот» в файле 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 

Тогда давайте говорить вам попробуйте вызвать помощника из основного.мл:

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 
+0

Действительно, теперь подпись не действует, поскольку все видно из основного. Я понял «два уровня робота», но понятия не имел, как исправить это, сохранив полезную подпись. –

+0

Если вы хотите убедиться, что только внутри модуля Robot видны внутри основного, тогда определите файл robot.mli, который экспортирует только то, что вы хотите экспортировать (я отредактирую свой ответ выше, чтобы показать это). – aneccodeal

5

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

  • Во-первых, вы можете Ограничьте подкатегория должна иметь правильную подпись:

    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" 
    

    Вы можете скомпилировать модули с помощью , а затем в main.ml просто используйте open Robot.

+0

Или лучше не открывать робот, а называть 'Robot.top()'. –

+0

и если '' 'Robot.Robot.top' '' слишком длинный для частого использования, напишите '' 'let module R = Robot.Robot в R.top' '' – lambdapower

Смежные вопросы