module Extension =
type Dictionary<'T,'U> with
member this.Update (x: Dictionary<_,_>) =
for kvp in x do
this.[kvp.Key] <- kvp.Value
this
/// This is wrong too, I wanted to use
/// static let EmptyDictionary = Dictionary<'T,'U>()
static member EmptyDictionary = Dictionary<'T,'U>()
/// Should not modify it, needs to be readonly.
member this.Empty = Dictionary<'T,'U>.EmptyDictionary
为了模仿python字典update
函数,我需要一个空字典,以避免每次不需要更新时实例化一个新字典。 (我也可以使用null
,但通常我会避免使用它。)
上面有一个警告“当'T:缺少相等时”的类型约束。
以下说明我的代码的用例。
假设x
是字典,我可以将其与y
合并(x
更新x.Update y
如果我不想更新x
但仍需要传递y
,我可以使用x.Update x.Empty
答案 0 :(得分:1)
我没有完全理解这个问题,但似乎写new Dictionary<'K, 'V>()
会在equality
上引入'K
约束。但由于泛型类型本身不需要约束,因此会导致不匹配。
所以,我不知道如何使用您使用的样式来修复定义,但我可能会使用一些不同的东西:
type Dictionary<'T,'U> with
member this.Update (x: IDictionary<_,_>) =
for kvp in x do
this.[kvp.Key] <- kvp.Value
this
module Dictionary =
let Empty<'T, 'U when 'T : equality> = Dictionary<'T,'U>()
这使用了一个事实,即您可以拥有一个与某个类型同名的模块,因此它会添加Update
作为扩展名,但Dictionary.Empty
是一个通用值。这让你写:
Dictionary.Empty.Update(dict [1, "hi"; 2, "bye"])
答案 1 :(得分:1)
根据F#规范:
14.11 CLI方法的附加限制
F#专门处理一些CLI方法和类型,因为它们在F#和GT中很常见。编程并导致极难发现的错误。对于&gt;的每次使用在以下构造中,F#编译器强加了额外的临时约束:
x.Equals(yobj)需要类型ty:x的静态类型的相等
x.GetHashCode()需要类型ty:x的静态类型的相等
new Dictionary()要求A:相等,对于任何不包含的重载>拿一个 的IEqualityComparer
因此,如果您不打算改变空字典,那么您可以为Dictionary<'K, 'V>
使用不同的构造函数重载并传递默认比较器。
目前,静态成员EmptyDictionary
将在每次通话时返回一个新的字典实例,我不确定这是故意的。您可以使用专用类型为每对类型参数
open System.Collections.Generic
module Extension =
type EmptyDictionaryHolder<'T, 'U>() =
static let value = new Dictionary<'T, 'U>(EqualityComparer<'T>.Default)
static member Value: IDictionary<'T, 'U> = value :> _
type IDictionary<'T,'U> with
static member EmptyDictionary = EmptyDictionaryHolder<'T, 'U>.Value
member this.Update (x: IDictionary<_,_>) =
for kvp in x do
this.[kvp.Key] <- kvp.Value
this
member this.Empty = Dictionary<'T,'U>.EmptyDictionary