Dictionary 为字典键入扩展名错误<';K、 &x27;V>;
下面的类型扩展Dictionary 为字典键入扩展名错误<';K、 &x27;V>;,dictionary,f#,extension-methods,Dictionary,F#,Extension Methods,下面的类型扩展 module Dict = open System.Collections.Generic type Dictionary<'K, 'V> with member this.Difference(that:Dictionary<'K, 'T>) = let dict = Dictionary() for KeyValue(k, v) in this do if not (that.Contains
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that:Dictionary<'K, 'T>) =
let dict = Dictionary()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict
模块Dict=
open System.Collections.Generic
使用
成员:此差异(即:字典)=
让dict=Dictionary()
对于此do中的键值(k,v)
如果不是,那么
dict.Add(k,v)
字典
给出了错误:
签名和实现不兼容,因为类型参数“TKey”的声明需要格式为“TKey:equality”的约束
但当我添加约束时,它会产生错误:
此类型扩展的声明类型参数与原始类型“Dictionary”上声明的类型参数不匹配
这一点尤其神秘,因为下面的类型扩展没有约束,可以正常工作
type Dictionary<'K, 'V> with
member this.TryGet(key) =
match this.TryGetValue(key) with
| true, v -> Some v
| _ -> None
使用
成员:此。TryGet(键)=
将此.TryGetValue(键)与
|对,v->一些v
|无
现在我有了一个奇怪的想法:只有在访问某些成员时才需要约束吗?问题在于您使用了
Add
方法。如果使用Dictionary
的这种方法,则F#将强制TKey
具有相等约束
在玩了一会儿之后,我甚至不确定是否有可能编写这个扩展方法。F#type系统似乎强制扩展方法的声明类型没有原始类型以外的其他约束(每当我添加相等
约束时,我都会得到一个错误)。此外,Individual扩展方法中列出的类型不能与列出的类型不同。我已经尝试了许多方法,但无法使其正常工作
最接近的方法是非扩展方法,如下所示
let Difference (this : Dictionary<'K, 'T>) (that:Dictionary<'K, 'T> when 'K : equality) =
let dict = Dictionary()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict
let Difference(this:Dictionary)(当'K:equality时,this:Dictionary)=
让dict=Dictionary()
对于此do中的键值(k,v)
如果不是,那么
dict.Add(k,v)
字典
也许另一个F#ninja能够证明我错了,就我所知,以下代码起到了作用:
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that: Dictionary<'K,'V2>) =
let diff =
this
|> Seq.filter (fun x -> not <| that.ContainsKey(x.Key))
|> Seq.map (fun x -> x.Key, x.Value)
System.Linq.Enumerable.ToDictionary(diff, fst, snd)
模块Dict=
open System.Collections.Generic
使用
请记住此区别(即:字典)=
让差异=
这
|>Seq.filter(fun x->not Seq.map(fun x->x.Key,x.Value)
System.Linq.Enumerable.ToDictionary(差异、fst、snd)
(编辑:CKoenig有一个很好的答案。)
嗯,我也没有马上想到一个办法
这里有一个非类型安全的解决方案,可能会为其他人提供一些疯狂的灵感
open System.Collections.Generic
module Dict =
type Dictionary<'K, 'V> with
member this.Difference<'K2, 'T when 'K2 : equality>(that:Dictionary<'K2, 'T>) =
let dict = Dictionary<'K2,'V>()
for KeyValue(k, v) in this do
if not (that.ContainsKey(k |> box |> unbox)) then
dict.Add(k |> box |> unbox, v)
dict
open Dict
let d1 = Dictionary()
d1.Add(1, "foo")
d1.Add(2, "bar")
let d2 = Dictionary()
d2.Add(1, "cheese")
let show (d:Dictionary<_,_>) =
for (KeyValue(k,v)) in d do
printfn "%A: %A" k v
d1.Difference(d2) |> show
let d3 = Dictionary()
d3.Add(1, 42)
d1.Difference(d3) |> show
let d4 = Dictionary()
d4.Add("uh-oh", 42)
d1.Difference(d4) |> show // blows up at runtime
open System.Collections.Generic
模块Dict=
使用
成员。差异模块Dict=
open System.Collections.Generic
使用
成员:此差异(即:字典)=
让dict=字典(this.Comparer)
对于此do中的键值(k,v)
如果不是,那么
dict.Add(k,v)
字典
编辑:
依照
F#特别处理一些特定的CLI方法和类型,因为它们在F#编程中很常见,并且导致很难找到错误。对于以下构造的每次使用,F#编译器都会施加额外的特殊约束:
x.Equals(yobj)
需要类型ty:equality
用于静态类型的x
x.GetHashCode()
需要类型ty:equality
用于x
new Dictionary()
要求A:equality
,对于不需要IEqualityComparer
哎呀……我奇怪的想法得到了证实。我已经尝试过几种方法,但我也觉得不可能。约束来自何方?它是否与贾里德指出的Add
的使用有关?除了编译器告诉你之外,还有其他方法知道何时需要这些约束吗?参见14.11:显然new Dictionary
添加了约束,这解释了为什么到Dictionary
是可以的。我永远不会达到这个目的。为什么用比较器初始化字典会绕过相等约束?@Daniel,我怀疑深夜阅读规范可能会产生与熬夜相反的效果——无论如何,对我来说;)
module Dict =
open System.Collections.Generic
type Dictionary<'K, 'V> with
member this.Difference(that:Dictionary<'K, 'T>) =
let dict = Dictionary(this.Comparer)
for KeyValue(k, v) in this do
if not (that.ContainsKey(k)) then
dict.Add(k, v)
dict