2017-03-11 50 views
0

這兩者之間有什麼區別嗎?關於Ocaml中模塊的簽名的困惑

我不知道他們的,我應該把我的.mli文件

module Comparable : sig 
    type t 
    val compare : t -> t-> int 
end 

module type Comparable = sig 
    type t 
    val compare : t -> t-> int 
end 

real world ocaml本書中,作者說的話接口,簽名,模塊式可以互換使用。

PS:我很樂意將問題標題更改爲更適合的問題,任何提議?

回答

3
module type Comparable = sig 
    type t 
    val compare : t -> t-> int 
end 

限定了模塊類型。在一個接口(例如.mli文件)中,它承諾實現(.ml)包含相同的模塊類型定義。

module Comparable : sig 
    type t 
    val compare : t -> t-> int 
end 

在接口中承諾提供相同類型的模塊。它相當於

module Comparable : Comparable 

(假設模塊類型確實定義了)。它聲明對應的.ml包含名爲Comparable子模塊

你應該把哪兩個放在你的.mli取決於你想要做出什麼承諾。兩者都有其用途。

模塊類型定義通常在接口中找到,如果它們需要作爲函子的參數。事實上,您的模塊類型Comparable等於Map.OrderedType,函數的參數類型爲Map.Make

上述子模塊的一個用例是提供了,它可以用作函子的參數。例如,一個.mli看起來是這樣的:

type stuff = ... 
val fancy : ... (* some operations on stuff *) 

module Comparable : Comparable with type t=stuff 

在這種形式,它將使類型stuff可用作地圖的主要類型。這就是說,如果你的例子是完整的現實世界的例子,那麼我懷疑你想要的是模塊類型定義,而不是子模塊:子模塊不會很有用;你沒有任何操作來構造t類型的任何東西。

1

說你的文件名爲m.mli。第一個定義是您使用的內容,如果相應的m.ml文件中有一個模塊Comparable。第二個是你用來聲明模塊類型(只是模塊的類型,而不是模塊)。在第一種情況下,有一個實際的compare,可稱爲M.Comparable.compare。在第二種情況下,沒有比較函數,只是一個類型聲明。

不可能知道哪個對你是正確的。他們都有道理。

1

.mli文件允許約束.ml文件,請參閱下面的例子:使用foo和將失敗,並foo1到編譯器時

/* foo.ml */ 
    let foo1 x y = x + y 
    let foo = foo1 

    /* foo.mli */ 
    val foo : int -> int -> int 

    /* main.ml */ 
    open Foo 
    let r = foo 4 5 
    /* let r = foo1 4 5 ;; */ 

ocamlbuild main.native只會編譯。

現在,當你定義一個模塊,你可以定義此模塊時,無論是隱藏着一些聲明:

module Comparable : sig 
    /* the exposed interface */ 
    end = struct 
    /* the computation */ 
    end 

或者定義類型的模塊:

module type Comparable = sig 
    /* the exposed interface */ 
    end 

您將能夠稍後在代碼中使用該類型來限制某個模塊。 與上面給出的例子(!!刪除.mli文件!!)

/* foo.ml */ 
    let foo1 x y = x + y 
    let foo = foo1 

    /* main.ml */ 
    module type T1 = sig 
    val foo : int -> int -> int 
    end 

    module F1 : T1 = Foo 
    let r = Foo.foo1 4 5 
    let r = F1.foo1 4 5 /* will fail because hiden by type T1 */ 
2

你的第一代碼段定義的模塊具有特定簽名 ,第二個直接限定簽名不是一個模塊。 理解上的差異,您的代碼例如可以rewriten到

module type COMPARABLE = sig 
    type t 
    val compare : t -> t-> int 
end 

module Comparable: COMPARABLE