generics - 类型参数支持加法的通用接口(interface)

标签 generics f#

我在 F# 中试图创建一个类型参数必须支持添加的通用接口(interface),所以我最终得到了这样的结果:

type IMyInterface<'b when 'b : (static member (+) : 'b * 'b -> 'b)> =
    abstract member myFunction : 'b -> 'b

不幸的是,这段代码给了我以下错误:

This code is not sufficiently generic. The type variable ^D when ^D : comparison and ^D : (static member ( + ) : ^D * ^D -> ^D) could not be generalized because it would escape its scope.



我找到了this question关于同样的问题,但我不确定我是否理解为什么必须将函数标记为 inline .

此外,由于您无法创建抽象成员 inline ,是否存在我可以在我的具体示例中使用的另一种解决方案?还是我必须找到另一种方法来实现这一目标?

最佳答案

首先,我想我不完全理解为什么你需要声明接口(interface)的类型参数支持加法 - 我想加法将用于 MyFunction 的实现,在这种情况下,接口(interface)的调用者不需要知道它。如果要公开添加,可以简单地将其添加为单独的方法:

type IMyInterface<'T> =
  abstract Add : 'T * 'T -> 'T
  abstract MyFunction : 'T -> 'T

我认为静态成员约束在 inline 之外的其他地方效果不佳。功能或 inline静态成员(但我可能错了)。如果您需要在泛型类型中使用数字操作,您可以使用捕获实现的技巧(在 inline 方法中)并将它们存储在接口(interface)中。在我的 blog about generic math in F# 末尾有一个例子.

诀窍是使用您需要的数字操作定义一个接口(interface),并将其作为附加参数传递给构造函数:
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)

到目前为止,这是以标准 .NET 方式使用接口(interface) - 接口(interface)表示数字操作,我们通过接口(interface)调用它们。现在,诀窍是添加 inline方法Create只需要两个参数并且需要+作为静态约束。然后该方法可以实现接口(interface)并将其传递给 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)

现在你可以写MyType<_>.Create(1, 2)+整数运算将被自动捕获并存储在一个接口(interface)中(这在您的其余代码中更容易使用)。

关于generics - 类型参数支持加法的通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15637854/

相关文章:

java - 是否可以创建通用枚举?

generics - 使用泛型的计算表达式

java - 类型 T 不是通用的;它不能用参数 <?> 泛型函数中的错误进行参数化

c# - 如何通过 Assembly 访问泛型类型来解决它们?

f# - 如何在 fsi 中取消定义?

java - 如何对多个耦合对象使用泛型?

f# - 我可以让返回类型随参数而变化,有点像 F# 中的 sprintf 吗?

.net - 当 Generic.List<T>.Add 是函数中的最后一个语句并且尾调用优化开启时的性能损失

.net - MailboxProcessor 在 Finalize 期间崩溃

haskell - 什么叫拆分列表的函数?