Structural Equality – or is it?

I was recently presented with a conundrum. We had constrained data valid for the domain in a record type. Sadly this record type contained a reference datatype, so built-in structural equality broke down as the reference type never was equal in the way we thought would make sense.

This gave me the opportunity to learn how you override the implementation of Equals and GetHashCode in F# which I was previously unfamiliar with.

This is the finished implementation of the record type, or one like it, rather:

type Structure =
Name: StructureName
Status: StructureStatus
Format: Regex
interface IComparable with
member this.CompareTo { Name = name; Status = status; Format = format } =
compare ( this.Name, this.Status, this.Format.ToString() ) (name, status, format.ToString())
interface IComparable with
member this.CompareTo obj =
match obj with
| null -> 1
| 😕 Structure as other -> (this :> IComparable<_>).CompareTo other
| _ -> invalidArg "obj" "not a Structure"
override this.Equals (o: obj) =
match o with
  | :? Structure as os ->
  (this.Name, this.Status, this.Format.ToString()) =
(os.Name, os.Status, os.Format.ToString())
| _ -> false
  override this.GetHashCode() =
  (this.Name, this.Status, thus.Format.ToString()).GetHashCode()

So yeah, ujse of pattern matching to determine data types in the non-generic functions and extensive use the built-in structural equality in tuples.

Very nice. With thanks to TeaDrivenDev and Isaac Abraham on Twitter (and this StackOverflow response)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s