Damian
Damian

Reputation: 2789

Case insensitive comparison on string fields of Record type

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

Answers (1)

scrwtp
scrwtp

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

Related Questions