使用 let 内联和成员约束,我将能够为已知成员进行鸭式输入,但如果我想定义一个像这样的通用函数怎么办:
让鸭包装器<'a>鸭= ...
带有签名 'b -> 'a 并且返回的值将是一个实现 'a 的对象(这将是一个接口)并将调用转发给鸭子。
我已经在 C# 中使用 Reflection.Emit 完成了这项工作,但我想知道 F# 反射、引用或其他构造是否会使其更容易。
关于如何做到这一点的任何建议?
阅读蒂姆斯回答后编辑 我想我会提供更多细节
当我写关于使用引用来帮助时,我的想法是这样的:
{new IInterface with member x.SayHello() = !!<@ %expr @>}
!!是将引用转换为函数的运算符,%expr 是该方法的工作单元。我可以将表达式转换为函数(我猜)但不知道如何
当然,这也不能完全做到这一点,因为 IInterface 将是 'a,我希望 F# 反射可能有一些方便的功能,以便我可以基于类型对象和一些函数值构造一个类型
编辑 作为 Tomas Petricek 答案的更新,我将提供一些代码来解释我的需求
type SourceRole =
abstract transfer : decimal -> context
and context(sourceAccount:account, destinationAccount) =
let source = sourceAccount
let destination = destinationAccount
member self.transfer amount =
let sourcePlayer =
{new SourceRole with
member this.transfer amount =
use scope = new TransactionScope()
let source = source.decreaseBalance amount
let destination = destination.increaseBalance amount
scope.Complete()
context(source,destination)
}
sourcePlayer.transfer(amount)
这是在 F#中移植“ DCI ”教科书示例的尝试。源和目标是 DCI 角色。这个想法是任何遵守特定合同的数据对象都可以播放这些。在这种情况下,合同很简单。source 需要一个名为 reduceBalance 的成员函数,destination 需要一个名为 increaseBalance 的成员函数。对于这种特定情况,我可以使用 let inline 和 member 约束来实现这一点。但是我想写一组给定接口和对象的函数。在这种情况下,它可能是源(作为对象)和
type sourceContract =
abstract decreaseBalance : decimal -> sourceContract
作为类型。结果将是一个 sourceContract 类型的对象,它将方法调用通过管道传递给源对象上具有相同名称的方法。