您好,我刚刚开始使用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继承自StatisticsBase。我该怎么做才能使该函数可用于从StatisticsBase继承的所有实体?
类型:
[<AllowNullLiteral>]
type StatisticsBase() =
member val Id = String.Empty with get,set
[<AllowNullLiteral>]
type GroupStats() =
inherit Stats()
StatisticsBase实际上是继承自C#类型并在存储库中使用,但我可以使用上面的代码重现错误
答案 0 :(得分:3)
经过多次来回,我们已经能够确定您的实际非工作代码是这样的(未来提示:提供更多信息):
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
必须返回GroupStats
。稍后,当编译器遇到M
的主体时,它会看到M
的返回值与参数t
相同,这意味着M
必须返回{ {1}}。但是,由于编译器已经知道,通过检查'T
的正文,M2
必须返回M
,因此GroupStats
必须是'T
。
如果在GroupStats
之前定义M
,则不会发生这种情况:在这种情况下,类型推断将首先遇到M2
的主体并正确确定其返回类型为{{} 1}},然后将与M
的正文匹配,这将没有问题。
根据以上内容,可以制定两个解决方案:首先,您可以在'T
之前定义M2
。其次,您可以只显式指定M
的返回类型:
M2
这样,它的返回类型将在第一次传递后被识别,并且问题消失。