Honestly, I'm a little surprised that you are even allowed to use static member constraints in a type declaration, but, as mentioned in @pad, when you place the ads in the correct order and delete the recursion, (although I'm not sure when moving to more complex examples will not have other restrictions):
type A< ^B when ^B : (static member MyMember : Unit -> Unit)> = { Field : unit } type BTy = { BField : Unit } static member MyMember () = () type TestA = { AField : A<BTy> }
In any case, I think using static member constraints in a type declaration is a bit more complicated. A cleaner way to do this is to define an interface that clearly describes (and documents) the members you need:
type IMyMember = abstract MyMember : unit -> unit
Now, static element constraints can still be used to create an implementation of an interface from a type that has the required element but does not implement the interface. Using this method, you should be able to implement the same functions as with the constraints of the static member on types (but in a more clear way):
/// Captures 'IMyMember' implementation from another type using static constraints let inline captureMyMember< ^B when ^B : (static member MyMember : Unit -> Unit)> = { new IMyMember with member x.MyMember () = (^B : (static member MyMember : Unit -> Unit) ()) }
The function, for example, will create IMyMember from your BTy type:
/// A type that contains field and a captured implementation of 'IMyMember' type A = { Field : unit Operations : IMyMember } let it = { Field = () Operations = captureMyMember<BTy> }
Also, I used the same technique in an article that shows how to write a generic digital code , and I think it worked really nicely there.
Tomas Petricek Oct. 15 2018-12-12T00: 00Z
source share