Moh*_*adi 5 parameters f# types
以下(简化)代码段取自我正在实现的应用程序,该应用程序始终使用静态解析的类型参数.
type A< ^B when ^B : (static member MyMember : Unit -> Unit)> = {
Field : unit
}
type TestA = {
AField : A< BTy >
}
and BTy = {
BField : Unit
} with
static member MyMember () = ()
Run Code Online (Sandbox Code Playgroud)
当我定义字段AField(AField : A< BTy >)的类型时,IntelliSense给出了以下错误:类型'BTy'不支持任何名为'MyMember'的运算符.
编辑.单独声明它们是有效的,但如果我有一个共同引用,我不能声明第三种类型放在顶部,其中包含两种类型的公共信息.我该怎么做才能避免这个问题?无论如何,如果我在下面定义let pluto = ("" :> obj) :?> A< BTy >它的定义,我想是因为这两种类型都是从let绑定中可见的.
Tom*_*cek 12
说实话,我有点惊讶你甚至被允许在类型声明中使用静态成员约束,但正如@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> }
Run Code Online (Sandbox Code Playgroud)
无论如何,我认为在类型声明中使用静态成员约束有点复杂.更简洁的方法是定义一个清晰描述(和文档)所需成员的界面:
type IMyMember =
abstract MyMember : unit -> unit
Run Code Online (Sandbox Code Playgroud)
现在,静态成员约束仍可用于从具有所需成员的类型创建接口的实现,但不实现接口.使用这种技术,您应该能够实现与对类型的静态成员约束完全相同的功能(但以更清晰的方式):
/// 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) ()) }
Run Code Online (Sandbox Code Playgroud)
例如,该函数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> }
Run Code Online (Sandbox Code Playgroud)
除此之外,我在一篇文章中使用了相同的技术,该文章展示了如何编写通用数字代码,我认为它在那里工作非常好.
您的实现@Tomas 满足了问题,但对您的解决方案的风格有些犹豫,因为它不尊重函数式编程范例。我想到了一个由 Haskell 的类型类实现产生的解决方案。\n已实现接口、抽象类等,以便 F# 环境能够与 .Net 环境进行交互,出于风格统一的原因,使用实现的代码在不需要与 .Net 库交互的上下文中,接口、抽象类等,在我看来,它是 \xe2\x80\x9cOverhead\xe2\x80\x9d (尽管 F# 是一种多范式语言)。这就是为什么我发现 Haskell 类型类的实现非常优雅的原因。下面我通过 F# 实现了 \xe2\x80\x9cHaskell Type Class\xe2\x80\x9d 代码来解决我的问题。
\n\ntype Operations< ^a> = \n { \n MyMember : unit -> unit\n }\n\ntype A< ^a> = {\n Operations : Operations< ^a>\n}\n\nand TestA = { \n AField : A< BTy > \n}\n\nand BTy = { \n BField : Unit \n}\n\nlet it = \n let BTy_operations : Operations< BTy > = { MyMember = fun () -> () }\n let A_of_BTy = { Operations = BTy_operations }\n { AField = A_of_BTy }\nRun Code Online (Sandbox Code Playgroud)\n