我有一个简单的包装器,用于向任意对象添加附加数据:
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 行:此类型参数的使用方式使其始终为"包装器
第 1 行:此代码的通用性不如其注释所需的通用性,因为显式类型变量 'T' 无法泛化。它被限制为"包装器
"。 第 3 行:泛型成员 'Append' 已在此程序点之前以非统一实例化使用。请考虑对成员重新排序,以便首先出现此成员。或者,显式指定成员的完整类型,包括参数类型、返回类型以及任何其他泛型参数和约束。
我在这里做了一些根本错误的事情,但我不理解编译器消息。
您收到错误消息,因为类型推断以某种方式推断泛型类型参数'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
,使其永远不会接受包装的参数 - 这就是古斯塔沃的答案所暗示的。