Module OCaml模块:包含和打开?

Module OCaml模块:包含和打开?,module,ocaml,Module,Ocaml,我是OCaml模块的新手,在没有将“include”和“open”结合使用的情况下,我还没有使用过自己的模块。 我试图将签名放在一个单独的.mli文件中,但没有成功 下面是我试图编译的一个最小(非)工作示例 ocamlc -o main Robot.ml main.ml 我需要做什么才能只使用“open”或“include”,但不能同时使用它们 文件“Robot.ml”: 文件“main.ml”(不工作): 文件“main.ml”(工作): 你有两级机器人。由于在文件Robot.ml中显式调

我是OCaml模块的新手,在没有将“include”和“open”结合使用的情况下,我还没有使用过自己的模块。 我试图将签名放在一个单独的.mli文件中,但没有成功

下面是我试图编译的一个最小(非)工作示例

ocamlc -o main Robot.ml main.ml
我需要做什么才能只使用“open”或“include”,但不能同时使用它们


文件“Robot.ml”:

文件“main.ml”(不工作):

文件“main.ml”(工作):


你有两级机器人。由于在文件Robot.ml中显式调用了模块“Robot”,因此需要打开Robot,然后调用Robot.top()。robot.ml文件中的任何内容都已隐式放在robot模块中

您可以去掉Robot.ml中额外的“module Robot”声明

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中添加了一个名为helper的函数:

let top () =
  begin
     Printf.printf "top\n"
  end

let helper () =
  Printf.printf "helper\n"
…然后定义robot.mli,如下所示:

val top: unit -> unit
然后,假设您尝试从main.ml调用helper:

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

有两种方法可以做到这一点:

  • 首先,您可以将子结构约束为具有正确的签名:

    module Robot : RobotSignature = struct ... end
    
    然后在
    main.ml
    中,您可以执行
    打开Robot.Robot
    :第一个
    Robot
    表示与
    Robot.ml
    关联的编译单元,第二个
    Robot
    是您在
    Robot.ml
    中定义的子模块

  • 您还可以删除一个级别并创建包含以下内容的
    robot.mli

    val top: unit -> unit
    
    let top () = 
      Printf.printf "top\n"
    
    (* Should not be visible from the 'main' *)
    let dummy () = 
      Printf.printf "dummy\n"
    
    robot.ml
    包含:

    val top: unit -> unit
    
    let top () = 
      Printf.printf "top\n"
    
    (* Should not be visible from the 'main' *)
    let dummy () = 
      Printf.printf "dummy\n"
    
    您可以使用
    ocamlc-crobot.mli和&ocamlc-crobot.ml
    编译模块,然后在
    main.ml
    中使用
    openrobot


确实如此,但现在签名没有效果,因为从主屏幕上可以看到所有内容。我理解“机器人的两个级别”,但不知道如何在维护有用的签名的同时修复它。如果您想确保只有机器人模块中的部分在main中可见,请定义一个Robot.mli文件,该文件只导出您想要导出的内容(我将编辑上面的回答以显示此内容)。我想您已经回答了您的问题。您可能还想阅读有关。但一旦您了解了
open
的功能,请立即联系我们。不要使用它,它会让你的代码更难理解。我通常会同意,但在这种情况下,目标是提供一个简单的“机器人库”,向初学者教授基本编程(特别是,但不限于OCaml)。因此,我希望尽可能避免使用Robot.top()语法。我认为,对于初学者来说,显式渲染他们正在处理的对象实际上会更容易理解。无论如何,您可能还想查看和的文档。或者最好不要
打开Robot
,而是调用
Robot.top()
。如果“Robot.Robot.top”太长,无法频繁使用,请在R.top中编写“let module R=Robot.Robot”
let top () = 
  Printf.printf "top\n"

(* Should not be visible from the 'main' *)
let dummy () = 
  Printf.printf "dummy\n"