f
単一の引数 を持つF# ジェネリック関数を構築していると仮定しましょう。この引数は、関数セマンティクスによってからintegral
までの .NET 整数型に制限される必要があります。System.SByte
System.Int32
System.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 1I
f 'a'
f 1.0
f 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