F# 如何将一个F函数从C应用程序传递到另一个F函数?

F# 如何将一个F函数从C应用程序传递到另一个F函数?,f#,class-library,c#-to-f#,F#,Class Library,C# To F#,我有一个F#类库程序集,它包含两个函数: let add a b = a + b 及 我有一个C#控制台应用程序,它引用了F#库,正在尝试执行以下操作: FSharpList<int> l = new FSharpList<int>(1, new FSharpList<int>(2, FSharpList<int>.Empty)); int result = myFsLibrary.aggregateList(l, 0, myFsLibrary.

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

let add a b = a + b

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

FSharpList<int> l = new FSharpList<int>(1, new FSharpList<int>(2, FSharpList<int>.Empty));
int result = myFsLibrary.aggregateList(l, 0, myFsLibrary.add);
FSharpList l=newfsharplist(1,newfsharplist(2,FSharpList.Empty));
int result=myFsLibrary.aggregateList(l,0,myFsLibrary.add);

但是,编译器抱怨[myFsLibrary.add]无法从“方法组”转换为
FSharpFunc

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

FuncConvert.FuncFromTupled(new FSharpFunc<Tuple<int, int>, int>(args => 
    arags.Item1 + args.Item2))
那么您的C#应用程序就可以使用:

List.AggregateListFriendly(Enumerable.Range(0, 10), 0, (a, b) => a + b));

原因是add作为一个普通的.Net风格的函数导出,并且具有粗略的签名

int add(int, int)
C#和大多数.Net语言将此视为一种方法,它接受2个
int
参数并返回一个
int
值。不过F#不这么看函数。相反,它将
add
视为一个函数,该函数取
int
并返回一个函数,该函数依次取
int
并返回
int
。这种函数视图使得实现像curry这样的操作非常容易

为了从C#世界观转变为F#,你需要做一些魔术,将一个方法自身折叠起来。我通过定义一组F#factory和扩展方法来实现这一点,为自己创造奇迹。比如说

[<Extension>]
type public FSharpFuncUtil = 

    [<Extension>] 
    static member ToFSharpFunc<'a,'b,'c> (func:System.Func<'a,'b,'c>) = 
        fun x y -> func.Invoke(x,y)

    static member Create<'a,'b,'c> (func:System.Func<'a,'b,'c>) = 
        FSharpFuncUtil.ToFSharpFunc func

其他人已经提供了答案,但我只是想说,你不应该这样做

不要将F列表暴露给C。不要向C#公开curried函数。阻抗失配在该边界处可见,因此最好在跨语言汇编边界处公开公共框架类型。看


获取更多建议。

为什么不?这是我不理解的建议之一。如果我想得到不可变集合的保证,那么F#List不是.NET中唯一可以传递不可变性的东西吗?如果使用IEnumerable,这就不能保证库的客户端的不变性。我只希望FSharpList是一个接口。。。
int add(int, int)
[<Extension>]
type public FSharpFuncUtil = 

    [<Extension>] 
    static member ToFSharpFunc<'a,'b,'c> (func:System.Func<'a,'b,'c>) = 
        fun x y -> func.Invoke(x,y)

    static member Create<'a,'b,'c> (func:System.Func<'a,'b,'c>) = 
        FSharpFuncUtil.ToFSharpFunc func
var del = FSharpFuncUtil.Create<int, int, int>(myFsLibrary.add);