Reputation: 2789
Is there a way to substitute the comparison of string fields in a F# record class to be case-insensitive without having to take full custom control of equality/comparison?
Subtracting Records from a Set using case-insensitive comparison is the closest I have found to an answer.
Upvotes: 4
Views: 1016
Reputation: 13577
If you want to do it in a clean way, I would suggest introducing a wrapper type for case insensitive strings. That way you can have the notion of case insensitive comparisons reflected in the types, and don't have to change the default structural comparisons on the records.
[<CustomEquality; CustomComparison>]
type CIString =
| CI of string
override x.Equals y = ...
override x.GetHashCode() = ...
interface System.IComparable with
member x.CompareTo y = ...
I left out the implementation of the methods - there's nothing fancy there, just use ToUpperInvariant
on the nested string whenever you access it.
Then you can modify your records like this:
type OldRecord = { field : string }
type NewRecord = { field : CIString }
and comparisons on the new type should show that { field = "TEST" } = { field = "test" }
.
The other solution I suggested (reflection-based) would be easy to put in place for a simple case, but it's dodgy. Making it work in a sensible way for all the possible cases is a non-trivial exercise, if you can even establish what "sensible way" means here.
Upvotes: 9