I think the clean approach in this case (even in F #) is to use basic object-oriented programming and define an interface with the required members (e.g. Property ):
type IHasProperty = abstract Property : int
Note that F # indicates that we are declaring an interface because it has only abstract elements and a constructor. Then you can implement the interface in your types:
type FooA = {...} interface IHasProperty with member this.Property = ... type FooB = {...} interface IHasProperty with member this.Property = ...
It is worth noting that any type of F # (including records, discriminatory associations and class classes) can implement interfaces. Now a generic function can simply take two arguments of type IHasProperty :
let sum (a: IHasProperty) (b: IHasProperty) = a.Property + b.Property
In this case, you don’t even need generics, but there are several tricks that generic tools can do with interfaces - you can require a parameter of type T to implement a specific interface, but this is not necessary here because F # automatically converts arguments from such types, like FooA to the interface when you write sum f1 f2 .
Using interfaces and types that are immutable often makes very good sense in F #. There may be a “more functional” solution to your problem, but this will require more context.
source share