可能重复:
Type extension errors
我想在F#中添加一个扩展方法到System.Collections.Generic.Dictionary。麻烦的是我似乎无法正确地获得类型约束。我希望以下内容能起作用:
type Dictionary<'k, 'd when 'k : equality> with
static member ofList (xs:list<'k * 'd>) : Dictionary<'k, 'd> =
let res = new Dictionary<'k, 'd> ()
for (k, d) in xs do
res.Add (k, d)
res
但是,编译器抱怨我的声明与Dictionary的声明不同。当我省略等式约束时,它不会产生那个特定的错误。但随后它警告它失踪了。非常感谢任何提示,最好是其他“提高警告级别”: - )
修改
非常感谢KVB提供我想要的答案。
type Dictionary<'k, 'd> with
static member ofList (xs:list<'k * 'd>) : Dictionary<'k, 'd> =
let res = new Dictionary<'k, 'd> (EqualityComparer<'k>.Default)
for (k, d) in xs do
res.Add (k, d)
res
编辑:以下是更好地解释我对RJ的回复的示例。它表明,在实例化类型时类型参数是可选的,前提是编译器可以推断它们。它编译时没有警告或错误。
type System.Collections.Generic.Dictionary<'k, 'd> with
static member test (dict:System.Collections.Generic.Dictionary<'k, 'd>) : bool =
dict.Values |> List.ofSeq |> List.isEmpty
let test (x:System.Collections.Generic.Dictionary<'k, 'd>) =
System.Collections.Generic.Dictionary.test x
答案 0 :(得分:5)
由于某种原因,类型参数的名称必须匹配 - 这对我来说很好用
open System.Collections.Generic
type Dictionary<'TKey, 'TValue> with
static member ofList (xs:list<'k * 'd>) : Dictionary<'k, 'd> =
let res = new Dictionary<'k, 'd> ()
for (k, d) in xs do
res.Add (k, d)
res
我不知道为什么会出现这种情况(30秒看看规范也没有提供任何线索)。
更新 - 错误实际上是Dictionary
参数与方法中写入的相同 - 执行
type Dictionary<'a, 'b> with
static member ofList (xs:list<'k * 'd>) : Dictionary<'k, 'd> =
let res = new Dictionary<'k, 'd> ()
for (k, d) in xs do
res.Add (k, d)
res
工作得很好。这实际上现在是有道理的。当参数相同时,由于'k:equality
,还有一个未指定的约束 - new Dictionary<'k,'d>
。但是,出于某种原因,我们不能在扩展定义中放置约束(避免重复?),因此存在错误。
答案 1 :(得分:3)
如果您需要各种集合的ofSeq
函数,您可能会考虑类似于C#集合初始值设定项的方法。也就是说,使用Add
方法使其适用于任何集合。这也回避了你目前的问题。
open System.Collections.Generic
open System.Collections.Concurrent
module Dictionary =
let inline ofSeq s =
let t = new ^T()
for k, v in s do
(^T : (member Add : ^K * ^V -> ^R) (t, k, v)) |> ignore
t
module Collection =
let inline ofSeq s =
let t = new ^T()
for v in s do
(^T : (member Add : ^V -> ^R) (t, v)) |> ignore
t
open Dictionary
let xs = List.init 9 (fun i -> string i, i)
let d1 : Dictionary<_,_> = ofSeq xs
let d2 : SortedDictionary<_,_> = ofSeq xs
let d3 : SortedList<_,_> = ofSeq xs
open Collection
let ys = List.init 9 id
let c1 : ResizeArray<_> = ofSeq ys
let c2 : HashSet<_> = ofSeq ys
let c3 : ConcurrentBag<_> = ofSeq ys
有趣的是,您甚至可以将其限制为具有特定构造函数重载的集合类型。例如,如果您想使用结构相等,则可以执行以下操作:
let t = (^T : (new : IEqualityComparer< ^K > -> ^T) (HashIdentity.Structural))
答案 2 :(得分:0)
您将无法删除警告,因为您指的是不存在的类型,Dictionary
而不是Dictionary<_,_>
。如果您想要访问它,可以创建一个Dictionary模块。
open System.Collections.Generic
type Dictionary<'a,'b> with
static member ofList (xs:list<'k*'v>) =
let res = new Dictionary<_,_> ()
for k, v in xs do
res.Add (k, v)
res
module Dictionary =
let ofList xs = Dictionary<_,_>.ofList xs
然后你摆脱警告。
Dictionary.ofList ["1",1;"2",2];;
val it : Dictionary<string,int> = dict [("1", 1); ("2", 2)]