F#:将接口(如 IComparable)添加到现有类型(例如来自 Fare 等库)

F#: Adding an interface (like IComparable) to an existing type (e.g. from a library like Fare)

Context:我在 F# 中使用 .net/c#-library Fare,我尝试使用例如Map.ofSeq。这失败了,因为 Fare.State 不支持比较,因为它没有实现 System.IComprable 接口(FS0001)。

出于天真,我尝试像这样添加 interface IComparable

type Fare.State with
    interface IComparable<Fare.State> with
        member this.CompareTo obj =
                               match box obj with
                               | :? Fare.State as other -> this.Id.CompareTo other.Id
                               | _ -> invalidArg "obj" "not a State"

然而,这是不可能的,因为 F# 要求应在类型的初始声明 (FS0909) 上声明已实现的接口。

我想到了以下解决方法:

  1. 引入一个包含 Fare.State 作为其唯一属性并实现 IComparable
  2. 的包装器类型
  3. 存储 ID 而不是实际的 ID Fare.State 并使用 Map 转换为需要的实际状态
  4. 使用一些技巧将 interface IComparable 添加到现有类型。

如果第三个选项不可能,哪个选项最合适?还有其他选择吗?

虽然 State 类型确实实现了(泛型)IComparable<'T>,但 F# 在比较约束中寻找的是(非泛型)IComparable。前者不是后者的子类型这一事实似乎是一个可悲的设计选择,但它会保留下来。

你的解决方法 1 和 2 对我来说很有意义。从设计的角度来看,我更喜欢 State 周围的简单记录包装器。但是,如果 ID 是唯一的,则可以考虑使用其他解决方法,如果有点笨拙的话。