F # -> Реализация IComparable для HashSet <'a> - PullRequest
2 голосов
/ 06 апреля 2011

Можно ли как-то реализовать IComparable для HashSet<'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>, так как база данных, с которой я работаю, не понимает любой fsharp-ishсписки вообще.

Ответы [ 2 ]

16 голосов
/ 06 апреля 2011

Я предполагаю, что вы хотите сравнить и приравнять Category с, принимая во внимание только Id, Name и SavePath (в этом порядке), делая запись так, как если бы 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; }

Однако, если вместо этого вы хотите сравнить на 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; }
2 голосов
/ 06 апреля 2011

См

http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx

Вкратце, я думаю, что вы хотите применить атрибуты CustomEquality и CustomComparison к этому типу, а затем реализовать его самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...