老实说,我有点惊讶您甚至可以在类型声明中使用静态成员约束,但正如@pad 所提到的,当您将声明按正确的顺序并删除递归时,它可以工作(尽管当您转向更复杂的示例时,我不确定是否会有其他限制):
type A< ^B when ^B : (static member MyMember : Unit -> Unit)> =
{ Field : unit }
type BTy =
{ BField : Unit }
static member MyMember () = ()
type TestA = { AField : A<BTy> }
无论如何,我认为在类型声明中使用静态成员约束有点复杂。一种更简洁的方法是定义一个清楚地描述(和记录)您需要的成员的接口:
type IMyMember =
abstract MyMember : unit -> unit
现在,静态成员约束仍可用于从具有所需成员但不实现接口的类型创建接口的实现。使用这种技术,您应该能够实现与对类型的静态成员约束完全相同的功能(但以更清晰的方式):
/// 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) ()) }
例如,该函数IMyMember
将从您的BTy
类型创建:
/// A type that contains field and a captured implementation of 'IMyMember'
type A =
{ Field : unit
Operations : IMyMember }
let it = { Field = ()
Operations = captureMyMember<BTy> }
另外,我在一篇展示如何编写通用数字代码的文章中使用了相同的技术,我认为它在那里工作得非常好。