2012-08-06 56 views
2

我定義了兩個記錄類型如下:訪問成員時,歧記錄類型有共同的標籤

(* in module A*) 
type reg = {name: string; mutable value: Big_int.big_int} 
type exp = Reg of reg | Other 

(* in module B*) 
type abstr = Top | Bot | Elt of int 
type register = {name: string; mutable value: abstr} 

在模塊B,我有一個名單,我稱之爲lexp,我正在做一個模式匹配。所以,我有這樣的事情:

List.fold_left (fun l elt -> 
    let str = 
     match elt with 
      | A.Reg r -> r.name 
      | _ -> failwith "exception" in 
     [email protected][{name = str; value = Bot}]) [] l 

但我得到以下錯誤:表達的類型爲A.reg但預計類型寄存器的。看起來模塊A中的定義被模塊B中的定義所隱藏。如果是,爲什麼會這樣?有人可以解釋嗎?

+1

你可以嘗試用'A.Reg'代替'A.reg'嗎? – dkim 2012-08-06 14:54:55

+0

這就是我在代碼中實際使用的內容 – 2012-08-06 15:11:28

回答

5

要從模塊使用記錄字段名稱,你需要輸入:

value.Module.field 

你的情況,那就是:

r.A.name 

我覺得Deokhwan金也是正確的,你想A.Reg而不是A.reg

回答「爲什麼它是這樣的」:獲得(美妙的和奇妙的)類型推斷的迴歸是編譯器不能從類型的事物中推斷重載名稱的含義。推論走向另一條路(本質上)。所以你不能基於類型區分name這兩個字段,你需要明確你的意思。整數算術運算符和浮點算術運算符之間的區別出現了類似的限制。

+0

因此,類型推斷是原因。謝謝 – 2012-08-06 15:16:47

5

記錄無法在OCaml中共享字段名稱。記錄類型exp中的字段的全名是A.nameA.value。與其他命名元素一樣,在模塊A中,您可以省略A.前綴。但是,在另一個模塊中,您必須使用完全限定的名稱(除非您已打開A)。換句話說,寫r.A.name來解決你的錯誤。

+0

我已經打開了A,但仍然必須使用完全限定名稱 – 2012-08-07 07:57:02