F#相同/可比较泛型类型

时间:2016-03-07 15:15:59

标签: f# compare equality

我有这样的记录类型:

type Node<'T> = { doStuff: 'T -> unit ; id: int }

如何实现相等/可比,以便只将id等同/比较?

注意:这需要在不同类型的节点之间工作。因此,等同/比较Node<int>Node<string>。当涉及仿制药时,这似乎并不重要。

2 个答案:

答案 0 :(得分:2)

可以通过一个共同的基本类型来完成:

type IHaveId =
    abstract Id : int
    inherit System.IComparable

type [<CustomEquality; CustomComparison>] Node<'T> =
    { DoStuff: 'T -> unit ; Id: int }

    interface IHaveId with
        member n.Id = n.Id

    override n.Equals n' =
        match n' with
        | :? IHaveId as n' -> n.Id = n'.Id
        | _ -> invalidArg "n'" "Tried to equate incompatible types."

    override n.GetHashCode () = n.Id.GetHashCode()

    interface System.IComparable with
        member n.CompareTo n' =
            match n' with
            | :? IHaveId as n' -> n.Id.CompareTo n'.Id
            | _ -> invalidArg "n'" "Tried to compare incompatible types."

请注意,这不是很快。另外,要小心:通过对Node<'T>的公共构造访问,可以构造执行不同但被视为等于的节点。

使用DoStuff的接口可以进行结构比较。如果对象及其ID是集中构建的,我会考虑[<ReferenceEquality>]并明确地将比较函数传递给需要它的集合(例如Set<_>Map<_>)。

答案 1 :(得分:1)

我猜想为该类型编写静态成员将是一些解决方案

static member compareNodes (n1:Node<_>) (n2:Node<_>) =
    n1.id.CompareTo(n2.id)