将FSharpFunc从F#返回到C#

时间:2011-10-11 17:00:27

标签: f# c#-to-f#

我想在F#中编写一个函数,它将以下类型签名公开给C#:

public static FSharpFunc<FSharpFunc<Unit,Unit>,Unit> foo(Action<Action> f)

在F#中,我尝试写作:

let foo (f : Action<Action>) : ((unit -> unit) -> unit) = ...

但是这产生了C#签名:

public static void foo(Action<Action> f, FSharpFunc<Unit,Unit> x)

F#将我的代码等效地处理为:

let foo (f : Action<Action>) (g : unit -> unit) : unit = ...

当然,这些相当于F#,但在C#中却截然不同。我能做些什么来制作我想要的C#吗? (F#2.0.0.0)

作为一个快速黑客,我把我的F#重写为:

let foo (f : Action<Action>) ((unit -> unit) -> unit)[] = ...

然后我只在C#中使用Head

3 个答案:

答案 0 :(得分:2)

或者:

  1. 使用val foo : Action<Action> -> ((unit -> unit) -> unit)添加签名文件。
  2. 使用名义类型的静态成员,而不是模块中的let-bound值。也就是static member foo (x:Action<Action>) : ((unit -> unit) -> unit) = ...

答案 1 :(得分:2)

如果你编写let foo x = fun () -> ...,那么F#编译器会优化代码并将其编译为一个带有两个参数的方法(而不是一个返回函数的方法,这是你需要的)。要获得函数值,您需要在返回函数之前“执行某些操作”:

// Will be compiled as method taking Action, FastFunc and returning void
let foo1(x : Action<Action>) : (unit -> unit) -> unit = 
  fun f -> f ()

// Will be compiled as method taking Action and returning FastFunc of FastFunc
let foo2(x : Action<Action>) : ((unit -> unit) -> unit) = 
  ignore ();
  fun f -> f ()

也就是说,以任何方式将F#函数类型暴露给C#都是错误模式,不应该这样做。如果你有一些应该在C#中使用的F#API,你应该将函数公开为委托,这样C#使用者可以自然地使用它们(不明确地将Action转换为F#函数)。在F#端编写包装通常更容易。

答案 2 :(得分:0)

这样的事情?

open System 
let foo(x : Action<Action>) : (unit -> unit) -> unit = failwith "..."