第 12 章 語言擴展

22 廣義 open 語句

(於 4.08 版本引入)

定義::= ...
   open  模組表達式
   open!模組表達式
 
規格::= ...
   open  擴展模組路徑
   open!擴展模組路徑
 
表達式::= ...
 letopen  模組表達式in表達式
 letopen!模組表達式in表達式
 

此擴展使得在模組結構和表達式中可以開啟任何模組表達式。類似的機制也適用於模組類型內部,但僅限於擴展模組路徑 (例如 F(X).G(Y))。

例如,一個模組可以在開啟時使用以下方式約束:

module M = struct let x = 0 let hidden = 1 end open (M:sig val x: int end) let y = hidden
錯誤:未綁定值 hidden

另一種可能性是立即開啟函子應用程序的結果

let sort (type x) (x:x list) = let open Set.Make(struct type t = x let compare=compare end) in elements (of_list x)
val sort : 'x list -> 'x list = <fun>

更進一步,此結構可以在結構體內部引入局部組件,

module M = struct let x = 0 open! struct let x = 0 let y = 1 end let w = x + y end
module M : sig val x : int val w : int end

一個重要的限制是,由 open struct ... end 引入的類型不能出現在封閉結構的簽名中,除非它們被定義為等於某個非局部類型。所以

module M = struct open struct type 'a t = 'a option = None | Some of 'a end let x : int t = Some 1 end
module M : sig val x : int option end

這樣可以,但是

module M = struct open struct type t = A end let x = A end
錯誤:此 open 引入的類型 t 出現在簽名中。如果 t 被隱藏,則值 x 沒有有效的類型。

不行,因為 x 無法被賦予除了 t 之外的任何類型,而 t 僅在局部存在。儘管如果 x 也是局部的,則以上程式碼會沒問題

module M: sig end = struct open struct type t = A endopen struct let x = A endend
module M : sig end

在簽名內,擴展的 open 僅限於擴展模組路徑,

module type S = sig module F: sig end -> sig type t end module X: sig end open F(X) val f: t end
module type S = sig module F : sig end -> sig type t end module X : sig end val f : F(X).t end

而不是

  open struct type t = int end

在這些情況下,可以使用局部替換(參見12.7.2)。

請注意,此擴展在類別定義中不可用

class c =
  let open Set.Make(Int) in
  ...