Context: I'm using the .net/c#-library Fare in F# and I try to use e.g. Map.ofSeq. This fails as Fare.State does not support comparision since it does not implement the System.IComprable interface (FS0001).
In my naivity, I tried to add the interface IComparable like this:
type Fare.State with
interface IComparable<Fare.State> with
member this.CompareTo obj =
match box obj with
| :? Fare.State as other -> this.Id.CompareTo other.Id
| _ -> invalidArg "obj" "not a State"
This however is impossible as F# requires the implemented interfaces should be declared on the initial declaration of the type (FS0909).
I thought of the following works-arounds:
- Introducing a wrapper-type that includes a
Fare.Stateas its only attribute and implementsIComparable - Storing the ID instead of the actual
Fare.Stateand use a Map to translate to the actual state where needed - Use some trick to add
interface IComparableto the existing type.
If the third option is impossible, which option is most appropriate? Are there other options?
While
Statetype does implement (generic)IComparable<'T>, what F# looks for in comparison constraint is (non-generic)IComparable. The fact that the former is not a subtype of the latter seems like a lamentable design choice, but it's here to stay.Your workarounds 1 and 2 make sense to me. From a design point of view, I would prefer a simple record wrapper around
State. But if ids are unique, going with your other workaround is conceivable, if a bit clunky.