F#显式成员约束:类型变量^ T无法一般化,因为它会逃避其范围

时间:2011-05-05 22:15:15

标签: f# generics

我正在尝试在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,但我没有看到为什么这个特殊的通用约束不允许“逃避”的明确解释。

3 个答案:

答案 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