C# 设计F#库以供F#和C使用的最佳方法#
我正试图用F#设计一个库。图书馆应便于F#和C#使用 这就是我被卡住的地方。我可以让它变得F#friendly,也可以让它变得C#friendly,但问题是如何让它对双方都友好 这里有一个例子。假设我在F#中有以下函数:C# 设计F#库以供F#和C使用的最佳方法#,c#,f#,C#,F#,我正试图用F#设计一个库。图书馆应便于F#和C#使用 这就是我被卡住的地方。我可以让它变得F#friendly,也可以让它变得C#friendly,但问题是如何让它对双方都友好 这里有一个例子。假设我在F#中有以下函数: let compose(f:'T->'TResult)(a:'TResult->unit)=f>>a 这在F#中完全可用: 让我们使用composeinfsharp()= 让composite=compose(趣味项目->项目.ToString)(趣味项目->打印“%A”项目
let compose(f:'T->'TResult)(a:'TResult->unit)=f>>a
这在F#中完全可用:
让我们使用composeinfsharp()=
让composite=compose(趣味项目->项目.ToString)(趣味项目->打印“%A”项目)
复合“foo”
复合“棒”
在C#中,compose
函数具有以下签名:
FSharpFunc组合(FSharpFunc f,FSharpFunc a);
但当然,我不希望签名中出现FSharpFunc
,我想要的是Func
和Action
,如下所示:
动作组合2(功能f,动作a);
为此,我可以创建如下compose2
函数:
let compose2(f:Func)(a:Action(f.Invoke>>a.Invoke)
现在,这在C#中完全可用:
void UseCompose2FromCs()
{
compose2((字符串s)=>s.ToUpper(),Console.WriteLine);
}
但是现在我们在使用F#中的compose2
时遇到了问题!现在我必须将所有标准的F#funs
包装到Func
和Action
,如下所示:
让我们使用compose2infsharp()=
设f=Func(趣味项目->项目.ToString())
让a=动作(趣味项目->打印“%a”项目)
设composite2=compose2 f a
composite2.调用“foo”
composite2.调用“bar”
问题是:我们如何为F和C用户提供一流的F编写的图书馆体验
到目前为止,我想不出比这两种方法更好的方法:
- 将该库完全面向F#用户
- 从.fsi文件中隐藏所有不必要的内容
- 在源代码级别重用第一个F#项目
- 创建.fsi文件,该文件隐藏该项目的所有内容
- 创建.fsi文件,该文件以C#方式公开库,使用C#习惯用法表示名称、名称空间等
- 创建委托给核心库的包装器,在必要时进行转换
编辑2: 从到目前为止的回答和评论中,我可以看出我的问题缺乏必要的深度, 可能主要是因为只使用了一个例子,其中F#和C#之间存在互操作性问题 出现函数值的问题。我认为这是最明显的例子,因此 让我用它来问这个问题,但同样给人的印象是 我唯一关心的问题是 让我提供更多具体的例子。我已经通读了最优秀的例子 文档(非常感谢@gradbot!)。文档中的指导原则(如果使用)确实解决了这个问题 一些问题,但不是全部 该文件分为两个主要部分:1)针对F#用户的指南;和2)关于 以C#用户为目标。它甚至没有试图假装有一套制服 方法,这正好呼应了我的问题:我们可以针对F,我们可以针对C,但问题是什么 针对两者的实际解决方案 提醒一下,我们的目标是创建一个用F#编写的库,可以从 F#和C#两种语言 这里的关键词是惯用的。问题不在于可能实现的通用互操作性 使用不同语言的库 现在来看看我直接从中得到的例子
- F#:一定要使用名称空间或模块来包含类型和模块。
惯用用法是将函数放在模块中,例如:
// library module Foo let bar() = ... let zoo() = ... // Use from F# open Foo bar() zoo()
- C#:一定要使用名称空间、类型和成员作为您的主要组织结构
组件(与模块相反),用于香草.NETAPI
这与F#准则不符,这个例子需要
要重新编写以适合C#用户:
但这样做,我们打破了F的惯用用法,因为 我们不能再使用[] Foo型= 静态成员栏()。。。 静态成员zoo()=。。。
和bar
而不在其前面加上zoo
Foo
- F#:在适合返回值时,一定要使用元组
- C#:避免在vanilla.NETAPI中使用元组作为返回值
- F:你喜欢我们吗
[<AbstractClass; Sealed>] type Foo = static member bar() = ... static member zoo() = ...