可能重复:输入
扩展错误
我想在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
Run Code Online (Sandbox Code Playgroud)
但是,编译器抱怨我的声明与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
Run Code Online (Sandbox Code Playgroud)
编辑:这是一个更好地解释我对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
Run Code Online (Sandbox Code Playgroud)
由于某种原因,类型参数的名称必须匹配 - 这对我来说很好
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
Run Code Online (Sandbox Code Playgroud)
我不知道为什么会这样(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
Run Code Online (Sandbox Code Playgroud)
工作得很好.这实际上现在是有道理的.当参数相同时,还有一个未指定的约束 - 'k:equality由于new Dictionary<'k,'d>.但是,出于某种原因,我们不能在扩展定义中放置约束(避免重复?),因此存在错误.
如果您需要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
Run Code Online (Sandbox Code Playgroud)
有趣的是,您甚至可以将其限制为具有特定构造函数重载的集合类型。例如,如果您想使用结构相等,您可以这样做:
let t = (^T : (new : IEqualityComparer< ^K > -> ^T) (HashIdentity.Structural))
Run Code Online (Sandbox Code Playgroud)