2

f単一の引数 を持つF# ジェネリック関数を構築していると仮定しましょう。この引数は、関数セマンティクスによってからintegralまでの .NET 整数型に制限される必要があります。System.SByteSystem.Int32System.Numerics.BigInteger

1つのアプローチは実装することです

let inline f (integral: 'a) =
    (* function body here *) ...

'aの本体の実際の内容から派生するコンパイラによって推定される制約に依存しfます。これは、整数の .NET 型のセットと一致する場合と一致しない場合があります。

別のアプローチは、既知の .NET 型に対して整数型のみが静的チェックを通過することを実際に保証する、明示的に厳選されたアプリオリな制約を強制する'aことです。たとえば、

let inline f (integral: ^a when ^a:(static member (|||): ^a * ^a-> ^a)) =
    (* function body here, unit for illustration *)()

また

let inline f< ^a when ^a : (static member (|||): ^a * ^a -> ^a)> (integral: ^a) =
    (* function body here, unit for illustration *)()

, f 1uy,すぐに静的型チェックに合格しますが、, ,f 1L合格しません。f 1If 'a'f 1.0f 1m

最初のアプローチよりも 2 番目のアプローチを使用する利点があるとすれば、それは何ですか?

最初の目標を達成するためのより慣用的な方法はありますか?

UPDATE 02/03/2014皮肉なことに、この回答を見た後、今日だけ@kvb のプロンプトから動作するコードを取得することができました:

let inline implementation integral = ((* whatever implementation here *)) 

type Integral = Integral with 
    static member ($) (Integral, value: byte) = implementation value
    static member ($) (Integral, value: sbyte) = implementation value
    static member ($) (Integral, value: int16) = implementation value
    static member ($) (Integral, value: uint16) = implementation value
    static member ($) (Integral, value: int) = implementation value
    static member ($) (Integral, value: uint32) = implementation value
    static member ($) (Integral, value: int64) = implementation value
    static member ($) (Integral, value: uint64) = implementation value
    static member ($) (Integral, value: bigint) = implementation value

let inline doit integral = Integral $ integral

doit 1
doit 1I
doit 1.0 // does not compile
doit 1.0m // does not compile
doit '1' // does not compile
4

2 に答える 2

1

可能性を正確に整数型に制限したい場合は、オーバーロードされた静的メソッドを使用することが 1 つの代替手段になります。コードの重複を減らすために、これらはすべて無制限のジェネリック関数として実装できます。

于 2013-05-24T16:20:09.770 に答える