覆盖F#set的比较

Mau*_*fer 13 f#

有没有办法覆盖F#集中的比较函数?

我没有看到任何具有IComparer<T>或比较功能的set构造函数:

  • Set.ofSeq 等人没有采取比较功能
  • FSharpSet(IComparer<T> comparer, SetTree<T> tree) 构造函数是内部的,因为
  • SetTree是内部和
  • SetTreeModule.ofSeq<a>(IComparer<a> comparer, IEnumerable<a> c) 显然也是内部的.

我的实际问题是我有一组,('a * 'a)我想要比较,例如(1,3)=(3,1).

我知道我可以将它包装在一个类型实现中IComparable<T>,但是有什么方法可以避免这种情况吗?

Tom*_*cek 18

我认为setF#核心库中可用的类型不允许指定自己的比较.但是,PowerPack中有一个标记版本的类型允许这样做.下面显示如何使用比较器创建一个使用模10比较整数的集合:

#r @"FSharp.PowerPack.dll"
open System.Collections.Generic
open Microsoft.FSharp.Collections.Tagged

type MyComparer() = 
  interface IComparer<int> with
    member x.Compare(a, b) = (a % 10).CompareTo(b % 10)

// Type alias for a set that uses 'MyComparer'
type MySet = Tagged.Set<int, MyComparer>

let comparer = new MyComparer()
let s1 = MySet.Create(comparer, [1; 2; 3])
let s2 = MySet.Create(comparer, [11; 14])

MySet.Union(s1, s2)
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 5

你需要按照你的建议使用"包装"类型.

(对于不可改变的类型,如F#SetMap,有自定义比较API的问题.由于每个操作返回,例如一个新的Set对象,新的对象需要共享的比较器(可能导致线程问题),并有决定什么没有什么好办法比较器的结果应使用例如结果Set.union的两组不同comparers,所以SetMap在这里避免总是直接使用在元件类型比较的混乱.作为托马斯提及,所述的PowerPack具有一个替代的API,使得所述的比较器部分type,例如,它启用了类型安全/比较安全的Union方法.)