2014-11-25 101 views
0

我有一個簡單的包裝,我用它來aditional的數據添加到任意對象:F#編譯錯誤與嵌套泛型

type Wrapper<'T>(data:'T) = 
    member val Data:'T=data with get 
    member val AdditionalProperty:int=0 with get 

然後我使用這些元素的單鏈表,在這裏我想約束的項目是Wrapper<'T>,這些元件被限定:

type LListItem<'T>(data:Wrapper<'T>) = 
    member val Data:Wrapper<'T>=data with get 
    member val Prev:LListItem<'T> option = None with get, set 

然後我假裝來管理這個類的鏈表:

1| type LList<'T>()= 
2| let mutable last:LListItem<Wrapper1<'T>> option = None 
3| member x.Append(wrapped:Wrapper1<'T>)= 
4|  let item = new LListItem<'T>(wrapped) 
5|  match last with 
6|  | None -> 
7|  last <- Some item 
8|  | Some l -> 
9|  item.Prev <- last 
10|  last <- Some item 

但在這種Append方法,我這些編譯錯誤:

  • 行1:這種類型的參數已在約束它始終爲「包裝<‘的方式使用T>’

  • 第1行:由於顯式類型變量'T'不能被推廣,因此該代碼不如其註釋所要求的通用。它被限制爲'Wrapper <'T>'。

  • 第3行:在此程序點之前,通用成員'Append'已用於非統一實例。考慮重新排序成員,以便首先發生這個成員。或者,請明確指定成員的完整類型,包括參數類型,返回類型以及任何其他通用參數和約束。

我在這裏做了一些根本性的錯誤,但我不明白編譯器消息。

回答

2

您會收到錯誤消息,因爲類型推斷以某種方式推斷泛型類型參數'T總是被約束爲Wrapper<'T>。這通常發生在你有一些代碼類型爲'T的代碼並將其傳遞到預期的Wrapper<'T>處。

在你的情況下,當你在LList類型中設置last時會發生這種情況。類型標註定義爲類型是LListItem<Wrapper<'T>> option

type LList<'T>()= 
    let mutable last:LListItem<Wrapper<'T>> option = None 

但是當你分配值,參數是LListItem<'T>。所以,你需要上面的行改成這樣:

type LList<'T>()= 
    let mutable last:LListItem<'T> option = None 

我懷疑LListItem<Wrapper<'T>>是一個錯誤,因爲LListItem總是需要包裹的論點。

編輯:其他選項來解決這個問題是要改變LListItem使其從未需要包裝參數 - 這正是古斯塔沃的回答暗示。