F#->为HashSet实现IComparable. [英] F# -> Implement IComparable for HashSet<'a>

查看:95
本文介绍了F#->为HashSet实现IComparable.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以以某种方式为HashSet<'a>实现IComparable?原因是我声明了以下记录:

Is it possible to somehow implement IComparable for a HashSet<'a>? The reason for this is that I have following record declared:

[<StructuralComparison>]
type Category = { 
    mutable Id: string; 
    Name: string; 
    SavePath: string;
    Tags: HashSet<Tag> }

and Tag = { Tag:string; }

如您所见,Category记录中的标签类型为HashSet<Tag>-为了将类别序列映射到Map,我将需要以某种方式实现IComparable.否则只会导致:

As you can see, then Tags in the Category record is of type HashSet<Tag> - and in order to map a sequence of Categories to a Map, I'll need to implement the IComparable somehow... else it will just result in:

结构,记录或联合类型 类别"具有 'StructuralComparison'属性,但是 组件类型"HashSet"的作用 不满足比较"

The struct, record or union type 'Category' has the 'StructuralComparison' attribute but the component type 'HashSet' does not satisfy the 'comparison'

请注意,除了HashSet<'a>之外,我不能使用其他任何东西,因为我正在使用的数据库完全了解任何令人毛骨悚然的列表.

Please note that I cant use anything else than a HashSet<'a> since the database I'm working with dosent understand any fsharp-ish lists at all.

推荐答案

我假设您想通过仅考虑IdNameSavePath(在这样的顺序),使记录的行为就像没有出现Tags一样:

I'll assume you want to compare and equate Categorys by taking only Id, Name, and SavePath into account (in that order), making the record behave as though Tags wasn't present:

open System
open System.Collections.Generic

[<CustomComparison; CustomEquality>]
type Category =
    { mutable Id : string;
      Name       : string;
      SavePath   : string;
      Tags       : HashSet<Tag> }
    member private this.Ident = this.Id, this.Name, this.SavePath
    interface IComparable<Category> with
        member this.CompareTo other =
            compare this.Ident other.Ident
    interface IComparable with
        member this.CompareTo obj =
            match obj with
              | null                 -> 1
              | :? Category as other -> (this :> IComparable<_>).CompareTo other
              | _                    -> invalidArg "obj" "not a Category"
    interface IEquatable<Category> with
        member this.Equals other =
            this.Ident = other.Ident
    override this.Equals obj =
        match obj with
          | :? Category as other -> (this :> IEquatable<_>).Equals other
          | _                    -> false
    override this.GetHashCode () =
        hash this.Ident

and Tag = { Tag : string; }

但是,如果相反,您想通过Name进行比较并以Id进行等价,则请考虑以下事项:

However, if instead you want to compare by Name and equate by Id then consider the following:

open System
open System.Collections.Generic

[<CustomComparison; CustomEquality>]
type Category =
    { mutable Id : string;
      Name       : string;
      SavePath   : string;
      Tags       : HashSet<Tag> }
    interface IComparable<Category> with
        member this.CompareTo { Name = name } =
            this.Name.CompareTo name
    interface IComparable with
        member this.CompareTo obj =
            match obj with
              | null                 -> 1
              | :? Category as other -> (this :> IComparable<_>).CompareTo other
              | _                    -> invalidArg "obj" "not a Category"
    interface IEquatable<Category> with
        member this.Equals { Id = id } =
            this.Id = id
    override this.Equals obj =
        match obj with
          | :? Category as other -> (this :> IEquatable<_>).Equals other
          | _                    -> false
    override this.GetHashCode () =
        this.Id.GetHashCode ()

and Tag = { Tag : string; }

这篇关于F#-&gt;为HashSet实现IComparable.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆