2011-04-05 60 views
1

是否有可能以某种方式实现IComparableHashSet<'a>?这样做的原因是,我有以下记录声明:F# - >实现HashSet的IComparable <'a>

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

and Tag = { Tag:string; } 

正如你所看到的,然后标签在Category记录HashSet<Tag>型的 - 并且为了分类的序列映射到地图,我会需要实现IComparable莫名其妙......否则只会导致:

的结构,记录或联合类型 “类别”有 “StructuralComparison”属性,但 组件类型“HashSet的”不 不满足'比较'

请注意,我不能使用别的比HashSet<'a>,因为我与dosent工作数据库了解任何fsharp上下的名单都没有。

回答

13

我假设你要比较,并只服用IdNameSavePath考虑(按顺序),使得记录行为就好像Tags等同Category S为不存在:

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 { Id = id; Name = name; SavePath = savePath } = 
      compare (this.Id, this.Name, this.SavePath) (id, name, savePath) 
    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; Name = name; SavePath = savePath } = 
      this.Id = id && this.Name = name && this.SavePath = savePath 
    override this.Equals obj = 
     match obj with 
      | :? Category as other -> (this :> IEquatable<_>).Equals other 
      | _     -> false 
    override this.GetHashCode() = 
     hash (this.Id, this.Name, this.SavePath) 

and Tag = { Tag : string; } 

但是,相反,如果你想通过Name进行比较,并通过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; }