使用泛型类型和静态成员的意外编译器警告

时间:2016-03-10 17:13:54

标签: generics f#

我想创建自己的列表类型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}

1 个答案:

答案 0 :(得分:6)

这是因为Empty<_>方法的类型参数不必与CountedList<_>类的类型参数匹配。所以CountedList<string>.Empty<double>()是一个有效的方法调用,它将返回CountedList<double>,编译器无法确定这是否是你想要的。

您可能希望将Empty设为非通用方法,并在其正文中使用List.empty<'T>(您可以将其称为CountedList<double>.Empty(),或仅CountedList.Empty()在上下文中,类型的泛型参数可以由编译器推断)。或者,您可能希望创建一个配套CountedList模块并在其中创建一个通用的empty函数,并从您的类中删除Empty<_>方法。