Reflection F#中的泛型duck键入?

Reflection F#中的泛型duck键入?,reflection,f#,duck-typing,dci,Reflection,F#,Duck Typing,Dci,使用let inline和member约束,我将能够为已知的成员进行duck类型化,但是如果我想定义这样一个通用函数,该怎么办 让duckwrapper'a,其中返回的值将是实现'a(将是一个接口)并将调用转发给duck的对象 我已经在C#中使用Reflection.Emit实现了这一点,但我想知道F#Reflection、引号或其他构造是否会使它更容易实现 关于如何做到这一点有什么建议吗 编辑 在阅读了TIM的答案后,我想我应该给出更多的细节 当我写关于使用引用语来帮助他人时,我想到的是: {

使用let inline和member约束,我将能够为已知的成员进行duck类型化,但是如果我想定义这样一个通用函数,该怎么办

让duckwrapper'a,其中返回的值将是实现'a(将是一个接口)并将调用转发给duck的对象

我已经在C#中使用Reflection.Emit实现了这一点,但我想知道F#Reflection、引号或其他构造是否会使它更容易实现

关于如何做到这一点有什么建议吗

编辑 在阅读了TIM的答案后,我想我应该给出更多的细节

当我写关于使用引用语来帮助他人时,我想到的是:

{new IInterface with member x.SayHello() = !!<@ %expr @>}
这是移植F#中的“教科书”示例的一次尝试。源和目标是DCI角色。它的想法是,任何遵守特定契约的数据对象都可以扮演这些角色。在这种情况下,合同很简单。源需要名为DecreateBalance的成员函数,目标需要名为increaseBalance的成员函数。 对于这种特定的情况,我可以使用let inline和member约束来实现这一点。 但是我想写一组函数,给出一个接口和一个对象。在这种情况下,它可以是源(作为对象)和

作为类型。结果将是一个sourceContract类型的对象,它将通过管道方法调用源对象上同名的方法。

F#reflection(
Microsoft.FSharp.reflection
)是一个简单的
System.reflection
API的F#友好包装器,因此我认为它不会在这里添加任何内容

引用不能定义新类型:(您需要定义一个新类型来执行基于接口的duck类型)

>;;
;;
---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(7,4):错误FS0449:引号不能包含对象表达式
> ;;
;;
---^^^^
stdin(8,4):错误FS0010:引号文字中出现意外的关键字“type”
反射。发射仍然是解决这个问题的方法

编辑:

我希望F#reflection可能有一些方便的函数,这样我就可以基于type对象和一些函数值构造一个类型

恐怕不行。以下是关于F#reflection的文档:

您可以使用中的组件编译F#引用。所以我认为您可以使用引号在运行时生成和执行代码。如果您编写一个表示函数的引号并对其进行编译,您将得到一个函数值,可以用来实现接口。以下是一个简单的例子:

#r "FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation

// Create a part using "Expr." calls explicitly
let expr = Expr.Value(13)
// Create a part using quotation syntax 
let expr2 = <@ (fun x -> x * %%expr) @>

// Compile & Run
let f = expr2.Compile()()
f 10
#r“FSharp.PowerPack.Linq.dll”
打开Microsoft.FSharp.quotes
打开Microsoft.FSharp.Linq.QuotationEvaluation
//使用“Expr.”显式调用创建零件
设expr=expr.值(13)
//使用引号语法创建零件
设expr2=x*%%expr)@>
//编译并运行
设f=expr2.Compile()()
F10
您可以混合使用引号语法和对
Expr
的调用,这使得从基本块编写代码更加容易。编译有点愚蠢(目前),因此生成的代码不会像通常的F#代码那样高效(但您需要在您的案例中对其进行度量)


我不太清楚您到底想做什么,所以如果您能提供更多详细信息,我可以给出更具体的答案。

请参阅我的编辑以回应您的编辑。F#反射无法生成代码。F#引用语不够强大,无法满足您的需求。在这里使用Reflection.Emit是正确的。F#使用结构类型,而不是duck类型。它们非常相似,因为它们都使用类型推断,但结构类型是静态的,而duck类型是动态的(也有其他区别)。听起来你想用OCaml中的一个函子来完成,但我不确定F#等价物是什么。你也可以用.NET远程处理来完成这个任务。@Brian远程处理代理是实现duck类型的另一种方法。然而,这种方法比在内存中生成包装类慢得多。@Niki我的任务(以及由此产生的问题)与使duck类型成为可能有关。结构类型要求两种类型的结构相同。类型要求运行时使用的部件相同。我只关心运行时使用的部分,也就是duck-typing,这与我的想法有很大的不同。我已经用一些示例代码更新了我的问题
type sourceContract = 
   abstract decreaseBalance : decimal -> sourceContract
> <@ { new IInterface with member x.SayHello = "hello" } @>;;

  <@ { new IInterface with member x.SayHello = "hello" } @>;;
  ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(7,4): error FS0449: Quotations cannot contain object expressions
> <@ type Test() = class end @>;;

  <@ type Test() = class end @>;;
  ---^^^^

stdin(8,4): error FS0010: Unexpected keyword 'type' in quotation literal
#r "FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation

// Create a part using "Expr." calls explicitly
let expr = Expr.Value(13)
// Create a part using quotation syntax 
let expr2 = <@ (fun x -> x * %%expr) @>

// Compile & Run
let f = expr2.Compile()()
f 10