2012-04-03 81 views
10

我是OCaml模塊的新手,我沒有設法使用我自己的模塊,但沒有將「include」和「open」結合在一起。 我試圖把簽名放在單獨的.mli文件中,但沒有成功。OCaml模塊:包含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'的作用,不要使用它,它會讓你更難理解你的代碼。 – 2012-04-03 17:57:41

+0

那麼我通常會同意,但在這種情況下,目標是提供一個簡單的「機器人庫」,教給初學者基本的編程(特別是,但不限於OCaml)。所以我寧願儘可能避免使用Robot.top()語法。 – 2012-04-03 18:09:22

+0

嗯,我認爲這實際上會讓初學者更加不可理解地渲染他們正在採取行動的對象。無論如何,您可能還想查看[open](http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd170)和[include]( http://caml.inria.fr/pub/docs/manual-ocaml/manual019.html#@manual.kwd171)。 – 2012-04-03 18:12:13

回答

11

你有兩個級別的機器人。由於您明確地在文件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.mli文件指定哪個是外部可用的功能。例如,假設您在robot.ml添加一個名爲幫手功能:

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

let helper() = 
    Printf.printf "helper\n" 

...然後你定義robot.mli如下:

val top: unit -> unit 

然後讓我們說你嘗試從main調用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 
+0

事實上,但現在簽名並沒有任何效果,因爲所有東西都可以從主體中看到。我瞭解「機器人的兩個層次」,但不知道如何修復它,同時保持有用的簽名。 – 2012-04-03 17:06:26

+0

如果你想確保只有機器人模塊內的模塊在主模塊內可見,那麼定義一個robot.mli文件,它只導出你想要導出的內容(我將編輯我的上面的響應來顯示它)。 – aneccodeal 2012-04-03 17:10:57

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()。 – 2012-04-03 17:59:16

+0

如果'''Robot.Robot.top'''對於頻繁使用來說太長了,寫'''讓模塊R = Robot.Robot in R.top''' – lambdapower 2012-04-03 20:12:31