该参数的使用方式限制它始终为 DerrivedType

The parameter has been used in a way that constrains it to always be DerrivedType

您好,我刚开始使用 F# 编程,但遇到了类型问题。 我有这个功能:

    member private this.UpdateStats<'T when 'T :> StatisticsBase>(passed: bool, stats: 'T) =
        //more stuff..
        stats

我是这样称呼它的:

this.UpdateStats<GroupStats>(true, GroupStats(Id = Guid.NewGuid()))

编译器说:

该参数的使用方式限制它始终为 GroupStats。

GroupStats 继承自 StatisticsBase。我必须做什么才能使该函数可用于从 StatisticsBase 继承的所有实体?

类型:

[<AllowNullLiteral>] 
type StatisticsBase() =
    member val Id = String.Empty with get,set

[<AllowNullLiteral>] 
type GroupStats() =
    inherit Stats()

StatisticsBase 实际上继承自 C# 类型并在存储库中使用,但我可以使用上面的代码重现错误

经过多次反复,我们已经能够确定您的实际非工作代码是这样的(未来提示:提供更多信息):

type SomeType() =
    member this.M2() =
        this.M<GroupStats>(true, GroupStats())

    member private this.M<'T when 'T :> Stats>(x: bool, t: 'T) =
        t

此代码确实会产生所描述的错误。这是因为 F# 类型推断是从上到下、从左到右进行的。但有一个例外:类(和其他相互递归的定义组)获得两次类型推断 - 首先是签名,然后是主体。

当编译器第一次遇到 M2 的主体时,它确定方法 M 必须 return GroupStats。后来,当编译器遇到M的主体时,它看到M的return值与参数t相同,这意味着M ] 必须 return 'T。但是由于编译器已经通过检查 M2 的主体知道 M 必须 return GroupStats,因此 'T 必须是 GroupStats.

如果M定义在M2之前,则不会发生这种情况:在这种情况下,类型推断将首先遇到M的主体并正确确定其return 类型为 'T,它将与 M2 的正文匹配,并且不会有问题。

从上面可以得出两种解决方案:首先,您可以在M2之前定义M。其次,您可以明确指定 M:

的 return 类型
    member private this.M<'T when 'T :> Stats>(x: bool, t: 'T): 'T =
        t

这样,它的return类型在第一遍后就知道了,问题就消失了。