F# -> Implement IComparable for HashSet<'a>

后端 未结 2 898
醉梦人生
醉梦人生 2021-01-19 17:59

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

<         


        
相关标签:
2条回答
  • 2021-01-19 18:41

    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; }
    

    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; }
    
    0 讨论(0)
  • 2021-01-19 18:58

    See

    https://docs.microsoft.com/en-gb/archive/blogs/dsyme/equality-and-comparison-constraints-in-f

    Briefly, I think you want to apply the CustomEquality and CustomComparison attributes to this type and then implement it yourself.

    0 讨论(0)
提交回复
热议问题