如何将F#函数从C#app传递到另一个F#函数?

Ste*_*mer 3 f# class-library c#-to-f#

我有F#类库程序集,它包含两个函数:

let add a b = a + b
Run Code Online (Sandbox Code Playgroud)

let rec aggregateList list init (op:int -> int -> int) =
    match list with
    |[] -> init
    |head::tail ->
        let rest = aggregateList tail init op
        op rest head
Run Code Online (Sandbox Code Playgroud)

我有一个C#控制台应用程序,它引用了F#库并尝试执行以下操作:

FSharpList<int> l = new FSharpList<int>(1, new FSharpList<int>(2, FSharpList<int>.Empty));
int result = myFsLibrary.aggregateList(l, 0, myFsLibrary.add);
Run Code Online (Sandbox Code Playgroud)

但是,编译器抱怨[myFsLibrary.add]无法从'方法组'转换为 FSharpFunc<int, FSharpFunc<int, int>>

Bri*_*ian 9

其他人提供了答案,但我会介入说你不应该这样做.

不要将F#列表暴露给C#.不要将curried函数暴露给C#.阻抗不匹配在此边界处是可见的,因此最好在跨语言汇编边界处公开常见的框架类型.看到

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp-component-design-guidelines.pdf

了解更多建议.


Tom*_*cek 5

您可以使用FSharpFunc委托显式创建函数.在C#中,创建将所有参数作为元组的函数更方便,因此您可以这样做,然后使用函数将函数转换为curry类型FuncConvert.就像是:

FuncConvert.FuncFromTupled(new FSharpFunc<Tuple<int, int>, int>(args => 
    arags.Item1 + args.Item2))
Run Code Online (Sandbox Code Playgroud)

但是,如果需要从C#代码中调用一些F#函数,建议使用C#友好接口公开函数.在这种情况下,我可以使用Func委托,第一个参数应该是IEnumerableF#特定的列表类型:

module List = 
    let AggregateListFriendly inp init (op:Func<int, int, int>) =
        aggregateList (List.ofSeq inp) init (fun a b -> op.Invoke(a, b))
Run Code Online (Sandbox Code Playgroud)

然后你的C#appplication可以使用:

List.AggregateListFriendly(Enumerable.Range(0, 10), 0, (a, b) => a + b));
Run Code Online (Sandbox Code Playgroud)