Disabling equality for (entity) types


#1

In F# you can disable equality or comparison for a type, like this:

[<NoEquality; NoComparison>]
type Contact = {
  ContactId : ContactId
  PhoneNumber : PhoneNumber
  EmailAddress: EmailAddress
  }

This is useful for entities which in most cases you do not want to be compared as a whole:

// compiler error!
printfn "%b" (contact1 = contact2)
//            ^ the Contact type does not
//              support equality

But where you want equality specifically to work on Id fields directly:

// no compiler error
printfn "%b" (contact1.ContactId = contact2.ContactId) // true

Can this be accomplished in ReasonML as well?


#2

Not at compile time, no. This is because the OCaml standard library ships with a ‘polymorphic equality’ operator, Stdlib.(=) (actually others as well) that try to do a universal equality comparison. Some people consider this dangerous and consequently there are libraries like Jane Street’s Base/Core that by default ‘hide’ these polymorphic comparison operators. Once they’re hidden you do get a compile error for your example. But then you need to define or use some derivation mechanism to derive comparison operators for all types. Base/Core also help with that.

Note that these are native libraries (at the time of writing), I’m not aware of any BuckleScript libraries which do this.


#3

Actually, I forgot that BuckleScript has an extra warning for all polymorphic compares–warning number 102! See https://dev.to/yawaramin/ocaml-reasonml-best-practice-warnings-and-errors-4mkm for details on this one.