简体   繁体   中英

F#: Adding an interface (like IComparable) to an existing type (e.g. from a library like Fare)

Context : I'm using the .net/c#-library Fare in F# and I try to use eg 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:

  1. Introducing a wrapper-type that includes a Fare.State as its only attribute and implements IComparable
  2. Storing the ID instead of the actual Fare.State and use a Map to translate to the actual state where needed
  3. Use some trick to add interface IComparable to the existing type.

If the third option is impossible, which option is most appropriate? Are there other options?

While State type 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM