generics - 将类型约束添加到派生类型F#(此代码不够通用)

标签 generics f# polymorphism type-constraints

我有这个界面:

type IMovingFunc< 'T > =
    abstract member Add : 'T -> unit

现在,我想创建一个实现Add函数并使用(+)运算符的泛型类型:
type MovingSum< ^T >(initial : ^T) =
    let mutable sum = initial

    interface IMovingFunc< ^T> with
        member inline this.Add x = sum <- sum + x

不幸的是,我收到此错误:

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



我尝试将类型约束添加到MovingSum,但没有帮助:
type MovingSum< ^T when ^T : (static member ( + ) : ^T * ^T -> ^T)>(initial : ^T) 

您能否告诉我如何解决此问题,或者还有其他方法可以解决此问题?

最佳答案

正如Fyodor在评论中提到的那样,类型不能具有与函数相同的静态解析约束(主要是因为静态约束是使用内联处理的,而您不能真正内联整个类型)。

解决此问题的一种方法是使约束在类型中显式,然后创建具有静态成员约束的函数,该函数捕获功能并将其传递给类型。

在您的示例中,您需要+运算符,因此我们可以将adder添加为该类型的参数:

type MovingSum<'T>(initial:'T, adder:'T -> 'T -> 'T) =
    let mutable sum = initial
    interface IMovingFunc<'T> with
        member this.Add x = sum <- adder sum x

这不需要静态成员约束,但是在创建MovingSum时需要提供额外的参数。这还不错,但是您可以通过定义一个内联函数来避免这种情况,该函数创建MovingSum并捕获+运算符:
let inline movingSum initial = 
  MovingSum(initial, fun a b -> a + b) :> IMovingFunc<_>

关于generics - 将类型约束添加到派生类型F#(此代码不够通用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40830158/

相关文章:

java - 如何禁止使用原始类型

java - 使用泛型来简化调用

java - 制作一个 Comparator 对象来对通用 List<?使用 Collections.sort() 扩展 T>

f# - 使用计算表达式避免厄运金字塔?

java - 使用多态性初始化对象列表

c# 泛型列表

F# 测量单位 - 'lifting' 值要 float<something>

f# - 如何在 F# 中对顺序值进行分组

ember.js - Ember 2 简单的多态关系

java - 为什么 "instanceof"不工作?