如何将空单例添加到字典类型?

时间:2015-02-16 15:03:47

标签: f#

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

2 个答案:

答案 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