2017-10-16 3 views
1

こんにちは私はF#でプログラミングを開始しました。 私はこの機能を持っている:パラメータは常にデリバティブ型に制限された形で使用されています

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

上記のコードでエラーを再現することができ、我々がされていますこのコードは実際にDESCRが生成されます

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

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

:あなたの実際の非稼働コードはこの(:より多くの情報を提供し、将来のための先端)のようなものであることを確認することができますibedエラー。これは、F#型推論が上から下、左から右に作用するからです。しかし、例外があります:クラス(および他の相互リクルート定義グループ)は型推論の2つのパスを取得します - 最初の署名、次に本体。

コンパイラが最初にM2の本文を参照すると、メソッドMが​​を返す必要があると判断します。後でコンパイラがMの本文を参照すると、Mの戻り値がパラメータtと同じであることがわかります。つまり、M'Tを返す必要があります。しかし、コンパイラはM2の本文を調べると、Mは​​を返さなければならないことを既に知っているので、'Tは​​である必要があります。

このMM2前に定義されている場合は発生しません。この場合には、型推論はまず、その後、M2の体と一致あろう、Mの体に遭遇し、正しく'Tするその戻り値の型を決定しますそして問題はないでしょう。

上記から、をM2の前に定義することができます。その戻り値の型は、最初のパスの後に知られるようになる、との問題が消え、

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

この方法:第二に、あなただけの明示的Mの戻り値の型を指定することができます。

+0

ありがとう、私は間違ったことを知っている。私が最初に私のUpdateStats関数を宣言してから、関数の代わりに関数を呼び出すと、すべてがうまく動作します。シーケンスが間違っているときに、タイプエラーが発生した理由を説明できますか?あなたが答えをシーケンスのもので更新するなら、あなたの答えに印をつけます。再度、感謝します! –

+0

私は答えを更新しました。 –

関連する問題