为Dictionary <'K,'V>键入扩展错误

Dan*_*iel 7 extension-methods f# dictionary

以下类型扩展名

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
Run Code Online (Sandbox Code Playgroud)

给出错误:

签名和实现不兼容,因为类型参数'TKey'的声明需要形式为'TKey:equality的约束

但是当我添加约束时,它会给出错误:

此类型扩展的声明类型参数与原始类型"Dictionary < , >" 上的声明类型参数不匹配

这尤其神秘,因为以下类型扩展没有约束并且有效.

type Dictionary<'K, 'V> with
  member this.TryGet(key) =
    match this.TryGetValue(key) with
    | true, v -> Some v
    | _ -> None
Run Code Online (Sandbox Code Playgroud)

现在我有一些奇怪的想法:只有在访问某些成员时才需要约束吗?

des*_*sco 4

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
Run Code Online (Sandbox Code Playgroud)

编辑

根据F# 规范(14.11 CLI 方法的附加约束)

一些特定的 CLI 方法和类型由 F# 进行特殊处理,因为它们在 F# 编程中很常见,并且会导致极难发现的错误。对于以下构造的每次使用,F# 编译器都会施加额外的临时约束:

  • x.Equals(yobj)需要类型ty : equality为静态类型x
  • x.GetHashCode()需要类型ty : equality为静态类型x
  • new Dictionary<A,B>() 需要A : equality,对于任何不需要的重载IEqualityComparer<T>