2017-10-16 67 views
1

嗨,我剛剛開始在F#編程,並堅持在類型問題。 我有這樣的功能:該參數已被用來限制它始終是DerrivedType

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

我打電話這樣說:

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

編譯器說:

enter image description here 參數已經在它約束的方式被使用始終是GroupStats。

GroupStats從StatisticsBase繼承。爲了使該功能可用於從StatisticsBase繼承的所有實體,我需要做些什麼?

類型:

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

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

StatisticsBase實際上是從一個C#類繼承,並在倉庫中使用,但我可以用上面

+0

您將不得不展示更多的代碼。我沒有提到你描述的最小實現的警告。我懷疑'UpdateStats'的代碼並不像你那麼簡單。 –

回答

3

代碼重現錯誤經過多次來回,我們一直能夠確定的是你的實際的非工作代碼是這樣的(提示爲未來:提供更多信息):

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

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

此代碼確實會產生DESCR ibed錯誤。這是因爲F#類型推理從上到下,從左到右。但是有一個例外:類(和其他相互重新定義的組)有兩個類型推論 - 第一個簽名,然後是主體。

當編譯器第一次遇到M2的主體時,它確定方法M必須返回​​。稍後,當編譯器遇到M正文時,它看到M的返回值與參數t相同,這意味着M必須返回'T。但是由於編譯器已經從檢查M2的主體知道,M必須返回​​,因此'T必須是​​。

如果MM2定義之前不會發生這種情況:在這種情況下,類型推斷首先會遇到的M身體和正確地確定它的返回類型爲'T,然後將與M2身體匹配,這將是沒有問題的。

從上面可以得出兩個解決方案:首先,您可以在M2之前定義M。其次,你可以只明確指定的M返回類型:

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

這樣一來,它的返回類型將第一遍後成爲衆所周知的,問題消失。

+0

謝謝,我知道我做錯了什麼。如果我首先聲明我的UpdateStats函數,然後調用函數而不是其他方式,一切正常。你可以或任何人解釋爲什麼當序列錯誤時我得到了類型錯誤?如果你用序列事物更新答案,我會標記你的答案。再次感謝! –

+0

我已經更新了答案。 –

相關問題