我想在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
。
答案 0 :(得分:2)
或者:
val foo : Action<Action> -> ((unit -> unit) -> unit)
添加签名文件。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 "..."