简体   繁体   English

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

[英]F# explicit member constraints: The type variable ^T could not be generalized because it would escape its scope

I'm attempting to use explicit member constraints in F#. 我正在尝试在F#中使用显式成员约束 The documentation says "F# supports the complete set of constraints that is supported by the common language runtime", but if I actually compile a class with such an explicit constraint, such as the following, I get quite the exotic error. 文档说“ F#支持公共语言运行时支持的完整约束集”,但是如果我实际上用这样的显式约束(例如以下内容)编译一个类,则会出现非常奇怪的错误。

type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)> =
    member this.F a b = a + b

reports 报告

error FS0670: This code is not sufficiently generic. 错误FS0670:此代码不够通用。 The type variable ^T when ^T : (static member ( + ) : ^T * ^T -> ^T) could not be generalized because it would escape its scope. 当^ T:(静态成员(+):^ T * ^ T-> ^ T)时,类型变量^ T不能被泛化,因为它将逃避其范围。

And reports it at the site of defining member this.F . 并在定义member this.F的位置报告。 What does this mean? 这是什么意思? What is the relevant scope? 相关范围是什么?

There are a number of approaches supported by the language for doing this sort of work. 该语言支持多种方法来执行此类工作。 A nice exploration can be found here on StackOverflow , but I've not seen a clear explanation of why this particular generic constraint is not allowed to 'escape'. 可以在StackOverflow上找到一个不错的探索,但是我还没有清楚地解释为什么不允许这种特殊的通用约束“转义”。

Member constrains need statically resolved type parameters. 成员约束需要静态解析的类型参数。 But statically resolved type parameters are not allowed on types (as in your example), only for inline functions and inline methods. 但是类型上不允许静态解析的类型参数(如您的示例所示),仅适用于内联函数和内联方法。

The underlying problem is probably that types as a whole cannot be inline. 潜在的问题可能是整个类型不能内联。

See also: http://msdn.microsoft.com/en-us/library/dd548046.aspx 另请参阅: http : //msdn.microsoft.com/en-us/library/dd548046.aspx

If you use an inline member like this: 如果您使用这样的内联成员:

type MyType() =
    member inline this.F a b = a + b

the types of a and b will automatically be correctly constrained. a和b的类型将被自动限制。

You need to mark the member inline (and add type annotations if you want to force the arguments to be of type ^T ): 您需要标记成员inline (如果要强制参数为^T类型,请添加类型注释):

type MyType<'T when ^T: (static member ( + ) : ^T * ^T -> ^T)>() =   
    member inline this.F (a:^T) (b:^T)  = a + b

I've also added a constructor, so that you can actually call the method: 我还添加了一个构造函数,以便您可以实际调用该方法:

MyType().F 1 2

As others have noted, it is rarely necessary to write out the explicit member constraints by hand since they will usually be inferred. 正如其他人指出的那样,几乎不需要手动写出显式成员约束,因为通常可以推断出它们。 Furthermore, in this case there's no reason to put the constraint on the type rather than the method, and having a type parameterized by a statically resolved type variable is not idiomatic. 此外,在这种情况下,没有理由将约束置于类型而不是方法上,并且通过静态解析的类型变量对类型进行参数化不是惯用的。

F# specification: F#规范:

A type of the form ^ident is a statically resolved variable type. ^ ident形式的类型是静态解析的变量类型。 A fresh type inference variable is created and added to the type inference environment (see §14.6). 将创建一个新的类型推断变量,并将其添加到类型推断环境中(请参见第14.6节)。 This type variable is tagged with an attribute indicating it may not be generalized except at inline definitions (see §14.7), and likewise any type variable with which it is equated via a type inference equation may similarly not be generalized. 用一个属性标记该类型变量,该属性指示除非在内联定义中(参见第14.7节),否则不能对其进行一般化,同样,通过类型推断方程式对其进行等同运算的任何类型变量也可以类似地不进行一般化。

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html http://research.microsoft.com/zh-cn/um/cambridge/projects/fsharp/manual/spec.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM