从C#调用一个高阶的F#函数

20

给定一个接受函数作为参数的 F# 高阶函数:

let ApplyOn2 (f:int->int) = f(2)  

还有C#函数

public static int Increment(int a) { return a++; } 

我如何使用Increment作为参数调用ApplyOn2(来自C#)?请注意,ApplyOn2被导出为Microsoft.FSharp.Core.FSharpFunc<int,int>,与Increment的签名不匹配。

3个回答

31

要从相应的C#函数获取FSharpFunc,请使用:

Func<int,int> cs_func = (i) => ++i;
var fsharp_func = Microsoft.FSharp.Core.FSharpFunc<int,int>.FromConverter(
    new Converter<int,int>(cs_func));

要从等效的 FSharpFunc 中获取 C# 函数,请使用

var cs_func = Microsoft.FSharp.Core.FSharpFunc<int,int>.ToConverter(fsharp_func);
int i = cs_func(2);

所以,在这种情况下,你的代码可能如下:

Func<int, int> cs_func = (int i) => ++i;
int result = ApplyOn22(Microsoft.FSharp.Core.FSharpFunc<int, int>.FromConverter(
            new Converter<int, int>(cs_func)));

有没有一个带有两个参数的函数示例? - Scott Nimrod
1
@ScottNimrod 看看这个,它有如何实现的示例:https://learn.microsoft.com/en-gb/archive/blogs/jaredpar/converting-system-funct1-tn-to-fsharpfuncttresult (F#使用函数的柯里化版本) - Miguel Marques

18

如果您希望提供更友好的交互体验,请考虑在F#中直接使用System.Func委托类型:

let ApplyOn2 (f : System.Func<int, int>) = f.Invoke(2)

您可以轻松地在C#中调用您的F#函数,就像这样:

MyFSharpModule.ApplyOn2(Increment); // 3

然而,你所编写的增量函数存在问题。为了使你的函数返回正确的结果,你需要使用前缀形式的增量运算符:

public static int Increment(int a) { return ++a; }

-3

只需创建对您的程序集的引用:

#r @"Path\To\Your\Library.dll"
let ApplyOn2 (f:int->int) = f(2)
ApplyOn2 Library.Class.Increment

问题不在于引用程序集。 问题在于ApplyOn2被导出为Microsoft.FSharp.Core.FSharpFunc<int,int>,它与Increment不匹配。 - sthiers
1
我已经尝试过它并且它可以工作:
ClassLibrary1.Class1.Increment;; 绑定会话到 'J:\Projects\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.dll'... val it : int -> int = fun:clo@0
let ApplyOn2 (f:int->int) = f(2);; val ApplyOn2 : (int -> int) -> int
ApplyOn2 ClassLibrary1.Class1.Increment;; val it : int = 2
- ssp
3
这是一个从F#调用C#的例子。正如你所指出的,F#在函数和委托类型转换方面更加宽容,但问题是关于如何从C#调用F#。 - Ray Vernagus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接