这个问题是下一个层次的问题
F# Set using custom class
--我想为泛型接口定义IComparable。
我有一组实现共享元数据交换接口的任意类型,
ITree
伊特雷
我意识到这些东西并不完全是惯用的F#,但我正在尝试与现有的C#和VB代码进行互操作,因此我希望尽可能使用.NET接口和比较。
open System
open System.Collections.Generic
// Simplified "generic" metadata type that all implementers agree on
type ITree =
abstract Path: string with get, set
abstract ModifyDate: DateTime with get, set
type Thing1(path, date) =
interface ITree with
member x.Path = path
member x.ModifyDate = date
// In reality, the types implementing ITree are going to
// come from different external assemblies
type Thing2(path, date) =
interface ITree with
member x.Path = path
member x.ModifyDate = date
let d1 = DateTime.Now
let d2 = DateTime.Now.AddMinutes(-2.0)
let xs : seq<ITree> = Seq.cast [ Thing1("/stuff", d1); Thing1("/dupe", d1); Thing1("/dupe", d1) ]
let ys : seq<ITree> = Seq.cast [ Thing2("/stuff", d2); Thing2("/dupe", d1) ]
// Then I would like to take advantage of F# Sets
// to do comparison across these things
let xset = Set.ofSeq xs
let yset = Set.ofSeq ys
let same = Set.intersect xset yset
let diffs = (xset + yset) - same
现在实际的问题是:这不会编译,因为
伊特雷
还没有实现
IComparable
. 我需要一个自定义的比较,有助于时钟歪斜,最终其他事情。
有没有办法定义比较函数
伊特雷
直接地
如果我试着去做
type ITree =
abstract Path: string with get, set
abstract ModifyDate: DateTime with get, set
interface IComparable<ITree> with
let Subtract (this: ITree) (that: ITree) =
this.ModifyDate.Subtract(that.ModifyDate)
match compare (this.Path, this.ParentPath) (that.Path, this.ParentPath) with
| 0 ->
// Paths are identical, so now for a stupid timespan comparison
match abs (Subtract this that).TotalSeconds with
| x when x > 60.0 -> int x
| _ -> 0
| x -> x
编译器认为
伊特雷
不再是一个抽象的接口,或是令人困惑的东西。
IComparer<T>
喜欢
type ITreeComparer =
interface IComparer<ITree> with
member x.Compare(this, that) = ...
但是我不知道该怎么说
Set...
使用该IComparer的函数。
(我假设一旦我弄明白如何申请
IComparer<T>
IEqualityComparer<T>
根据需要。)
编辑:
我能行
let x = new HashSet<ITree>(a |> Seq.cast<ITree>, new ITreeEqualityComparer())
使用普通的.NET集合,这应该足以解决此问题;然而,我仍然想知道是否有更好的方法来做我想做的事情。