2012-02-15 126 views
6

我在OCaml中構建了兩個包含相同變體類型的庫。這個變體的細節並不是太重要,除非它非常大,並且手動爲它編寫轉換函數會很麻煩。 (它實際上是使用ocamlidl從C轉換而來的bfd_architecture枚舉)。OCaml等效類型

我現在正在使用這兩個庫編寫一個程序。特別是,我打電話給A.f,它返回A.variant_type的值,我需要在調用B.g時使用該值,它將B.variant_type的值作爲輸入。

有沒有什麼辦法可以告訴OCaml A.variant_type和B.variant_type是真的是一樣的類型,因此可以將值從一個值轉換爲另一個值呢?這些庫是獨立的,所以它們不應該互相引用。現在我使用Obj.magic來完成轉換,但這是一個破解。

+0

爲什麼你不能像ygrek所說的那樣,讓這兩個庫共享相同的變體類型,而不是生成具有相同結構的兩個不同的變體? – gasche 2012-02-15 15:27:48

+4

換句話說,將變體類型放入第三個模塊中,並在其他模塊中使用它。您可以「打開」模塊以使命名更輕量化。 – 2012-02-15 16:07:40

回答

1

你不必使用Obj.magic,但你必須使用一些「神奇」,

external convertAB : A.t -> B.t = "%identity" 
external convertBA : B.t -> A.t = "%identity" 

足以做轉換。當然,我明白你的關切;這兩種類型必須完全相同,否則您將處理運行時錯誤。如果完全可能且相關,則將這些變體轉換爲Polymorphic Variants即可解決問題。

+1

使用多態變體是解決一般問題的好方法。在我的情況下,我使用ocamlidl來生成變體類型,並且我沒有看到可選項來強制它輸出多態變體。 – 2012-02-15 16:00:48

+2

我相信你知道這一點,但使用''%identity'''和使用'Obj.magic'完全相同(事實上「相同」)。如果可能的話,你真的想避免它們。 – 2012-02-15 16:09:15

+0

哦,是的。我只是看着源頭。很高興知道。 – nlucaroni 2012-02-15 16:12:11

8

我相信沒有乾淨的方法,除非這些庫有一些定義這種類型的共同依賴(即在構建時引用兩個庫的相同模塊)。

3

如果您確實希望變體類型出現在兩個庫中,您還可以強制檢查它們是否相同。在第二個庫中,您可以編寫:

type t = OtherLib.t = | A | B | C | ... 

這將使編譯器驗證OtherLib.t = A | B | C | ...並使兩種類型相同。我不認爲它真的解決了你的問題,因爲你可能不想改變任何一個庫。

我通常會這樣做,當我想保留一個類型的不同版本(因爲它們保存在稍後我想要讀取的文件中),並且我希望每個版本都明確構造函數,同時保持與當前版本。

+0

這令人沮喪接近需要的東西。令人驚訝的是,你可以做到這一點,但不能做t = Firstlib.t = Secondlib.t。 – 2012-02-16 01:46:22