我想创建自己的列表类型CountedList<'T>
,其中包含一个普通的F#列表以及列表中#元素的计数(所以我不必遍历整个列表来获取元素数量。)
这是我的尝试:
type CountedList<'T> = {List: 'T list; Count: int}
static member Empty<'a> () = {List=List.empty<'a>; Count=0}
member this.AddOne(element) = {this with List=element::this.List; Count=this.Count + 1}
我们的想法是从某个类型的CountList.Empty开始,然后通过AddOne方法添加一个元素。
但是,当我尝试用这个创建空列表时:
let emptyDoubleList = CountedList.Empty<double>()
我收到以下警告:
The instantiation of the generic type 'CountedList' is missing and can't be inferred from the arguments or return type of this member. Consider providing a type instantiation when accessing this type, e.g. 'CountedList<_>'.
然后直接这样做:
let directEmptyDoubleList = {List=List.empty<double>; Count=0}
不发出警告。
为什么我会收到此警告?编译器是否应该能够意识到它是一个CountedList?此外,任何有关如何改进我的CountedList实现的建议也将受到赞赏。
以下是完整的代码示例:
type CountedList<'T> = {List: 'T list; Count: int}
static member Empty<'a> () = {List=List.empty<'a>; Count=0}
member this.AddOne(element) = {this with List=element::this.List; Count=this.Count + 1}
let emptyDoubleList = CountedList.Empty<double>() //Why does this give me a warning??
let directEmptyDoubleList = {List=List.empty<double>; Count=0}
答案 0 :(得分:6)
这是因为Empty<_>
方法的类型参数不必与CountedList<_>
类的类型参数匹配。所以CountedList<string>.Empty<double>()
是一个有效的方法调用,它将返回CountedList<double>
,编译器无法确定这是否是你想要的。
您可能希望将Empty
设为非通用方法,并在其正文中使用List.empty<'T>
(您可以将其称为CountedList<double>.Empty()
,或仅CountedList.Empty()
在上下文中,类型的泛型参数可以由编译器推断)。或者,您可能希望创建一个配套CountedList
模块并在其中创建一个通用的empty
函数,并从您的类中删除Empty<_>
方法。