F# - >为HashSet实现IComparable <'a>

ebb*_*ebb 2 f#

是否有可能以某种方式实现IComparableHashSet<'a>?原因是我有以下记录声明:

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

and Tag = { Tag:string; }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,那么Category记录中的标签是类型的HashSet<Tag>- 为了将一系列类别映射到一个Map,我需要以IComparable某种方式实现...否则它只会导致:

struct,record或union类型'Category'具有'StructuralComparison'属性,但组件类型'HashSet'不满足'comparison'

请注意,我不能使用除了之外的其他任何东西,HashSet<'a>因为我正在使用的数据库可以理解任何fsharp-ish列表.

ild*_*arn 16

我假设你要比较和相当于Category只以小号Id,NameSavePath考虑(按顺序),使得记录行为就好像Tags不存在:

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; }
Run Code Online (Sandbox Code Playgroud)

但是,如果你想要比较by Name和equate,Id那么请考虑以下内容:

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; }
Run Code Online (Sandbox Code Playgroud)