我正在尝试在F#中使用explicit member constraints。文档说“F#支持公共语言运行库支持的完整约束集”,但是如果我实际上编译了一个具有这种显式约束的类,例如以下内容,我就会遇到异乎寻常的错误。
type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)> =
member this.F a b = a + b
报告
错误FS0670:此代码不够通用。 ^ T时的类型变量^ T :(静态成员(+):^ T * ^ T - &gt; ^ T)无法推广,因为它会逃避其范围。
并在定义member this.F
的网站上报告。这是什么意思?相关范围是什么?
该语言支持多种方法来完成此类工作。可以找到一个很好的探索here on StackOverflow,但我没有看到为什么这个特殊的通用约束不允许“逃避”的明确解释。
答案 0 :(得分:8)
成员约束需要静态解析的类型参数。但是类型上不允许使用静态解析的类型参数(如示例所示),仅适用于内联函数和内联方法。
潜在的问题可能是整个类型不能内联。
另请参阅:http://msdn.microsoft.com/en-us/library/dd548046.aspx
如果你使用这样的内联成员:
type MyType() =
member inline this.F a b = a + b
a和b的类型将自动被正确约束。
答案 1 :(得分:3)
您需要标记成员inline
(如果要强制参数为^T
类型,则添加类型注释):
type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)>() =
member inline this.F (a:^T) (b:^T) = a + b
我还添加了一个构造函数,以便您可以实际调用该方法:
MyType().F 1 2
正如其他人所指出的那样,很少有必要手工写出明确的成员约束,因为它们通常会被推断出来。此外,在这种情况下,没有理由将约束放在类型而不是方法上,并且通过静态解析的类型变量参数化的类型不是惯用的。
答案 2 :(得分:1)
F#规范:
一种形式^ ident是一种 静态解析变量类型。一个 新型推理变量是 创建并添加到该类型 推理环境(见§14.6)。 此类型变量标记为 指示它可能不是的属性 除内联外,一般化 定义(见§14.7),同样如此 与之相关的任何类型变量 通过类型推断方程等同 也许同样不能概括。
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html