2012-11-24 28 views
5

我有兩個模塊。一個定義變量類型:Ocaml中的縮寫構造函數名稱

module A = struct 
    type foo = Bar of material | Baz | Boo 

    (* other stuff *) 
end 

,我想能夠使用foo的變種既是建設者和在另一個模塊

module B = struct 
    type foo = A.foo (* I can abbreviate A.foo by assigning it a local alias *) 

    let f (x : foo) = match x with 
    | Bar m  -> Bar (g m) (* Any way to abbreviate Bar and friends? *) 
    | Baz | Boo -> x 
end 

左側的側部,但每"referring to named objects"我有一個模塊路徑前綴的不同名稱:

let f (x : foo) = match x with 
    | A.Bar m   -> A.Bar (g m) 
    | A.Baz | A.Boo -> x 

有沒有辦法跳過避免ü唱歌模塊路徑短於open ing並從A拉動所有其他的東西?

回答

9

您可以在本地打開:

let f (x : foo) = A.(match x with 
    | Bar m  -> Bar (g m) 
    | Baz | Boo -> x) 

let f (x : foo) = 
    let open A in 
    match x with 
    | Bar m  -> Bar (g m) 
    | Baz | Boo -> x) 

你可以在一個子模塊定義Bar,使更少的東西暴露:

module A = struct 
    module BasicDataAndOps = struct 
    type foo = Bar of material | Baz | Boo 
    end 
    open BasicDataAndOps 
    (* other stuff *) 
end 

module B = struct 
    open A.BasicDataAndOps 
    ... 

對於境外使用模式,你可以在B中定義一個「智能構造函數」:

let bar m = A.Bar m 

ETA:我忘記了重新定義類型定義的可能性,在Ashish Argwal的回答中描述:type foo = A.foo = Bar of material | Baz | Boo。鑑於您的例子中已經有類型縮寫,這是最好的答案。

type-based label disambiguation有一些可能有用的工作,但它可能不會被接受進入該語言。

+0

輝煌。謝謝。 –

+1

如果通過「幕後」工作,你所指的是[基於類型的標籤消除歧義的建議](http://gallium.inria.fr/~scherer/gagallium/resolving-field-names/),那麼(1 )它最終可能不被接受,(2)它應該適用於(非多態)變體構造函數以及記錄標籤。 – gasche

+1

從3.12版本開始,OCaml中可以使用open in語法。 – didierc

2

除了lukstafi給出的答案之外,還可以在定義B.foo時重新聲明構造函數。

module A = struct 
    type foo = Bar | Baz 
end 

module B = struct 
    type foo = A.foo = Bar | Baz 

let f (x : foo) = match x with 
    | Bar -> "bar" 
    | Baz -> "baz" 

end 
+0

這是[3.2]中的* type-equation *位(http://askra.de/software/ocaml-doc/3.12/manual016.html#toc54)? –