我在F#中试图创建一个通用接口,其中类型参数必须支持添加,所以我最终得到这样的东西:
type IMyInterface<'b when 'b : (static member (+) : 'b * 'b -> 'b)> =
abstract member myFunction : 'b -> 'b
Run Code Online (Sandbox Code Playgroud)
不幸的是,这段代码给了我以下错误:
此代码不够通用.类型变量^ D当^ D:比较和^ D :(静态成员(+):^ D*^ D - > ^ D)无法推广,因为它会逃避其范围.
我发现了关于同样问题的这个问题,但我不确定我理解为什么必须将该功能标记为inline.
此外,既然你不能成为一个抽象的成员inline,我可以在我的具体例子中使用另一种解决方案吗?或者我是否必须找到另一种方法来实现这一目标?
首先,我想我不完全理解为什么你需要声明接口的类型参数支持加法 - 我想在实现中会使用加法MyFunction,在这种情况下接口的调用者不需要知道关于它.如果要公开添加,只需将其添加为单独的方法:
type IMyInterface<'T> =
abstract Add : 'T * 'T -> 'T
abstract MyFunction : 'T -> 'T
Run Code Online (Sandbox Code Playgroud)
我认为静态成员约束在其他地方比在inline函数或inline静态成员中不能很好地工作(但我可能是错的).如果需要在泛型类型中使用数值运算,则可以使用捕获实现(在inline方法中)并将它们存储在接口中的技巧.我的博客末尾有一个关于F#中的泛型数学的例子.
诀窍是使用您需要的数字操作定义一个接口,并将其作为附加参数传递给构造函数:
type IAddition<'T> =
abstract Add : 'T * 'T -> 'T
type MyType<'T>(a:'T, b:'T, add:IAddition<'T>) =
member x.Sum = add.Add(a, b)
Run Code Online (Sandbox Code Playgroud)
到目前为止,这是以标准.NET方式使用接口 - 接口表示数字操作,我们通过接口调用它们.现在,诀窍是添加只接受两个参数的inline方法Create,并且需要+作为静态约束.然后,该方法可以实现接口并将其传递给MyType最后一个参数:
static member inline Create(a:^N, b:^N) =
let ops =
{ new IAddition< ^N > with
member x.Add(a, b) = a + b }
MyType< ^N >(a, b, ops)
Run Code Online (Sandbox Code Playgroud)
现在您可以编写MyType<_>.Create(1, 2)并且+整数操作将被自动捕获并存储在一个界面中(在其余代码中更容易使用).
| 归档时间: |
|
| 查看次数: |
1530 次 |
| 最近记录: |