2016-12-06 5 views
2

数値型のMinValueMaxValueにアクセスできる数値ジェネリック関数が必要でした。すべてのBCLタイプはこれらのメンバーを持っているので、私はこのようなものを書いて逃げることができると思った:数値ジェネリックを使用してネイティブ数値型の最小値/最大値を取得すると、Int32.MaxValueが存在しないように見える

let inline zeroOrMax(x: ^a) = 
    match x with 
    | a when a = LanguagePrimitives.GenericZero -> x 
    | a when a = LanguagePrimitives.GenericOne -> 
     let maxVal = (^a: (static member MaxValue : ^a)()) 
     maxVal 
    | a when -a = LanguagePrimitives.GenericOne -> 
     let maxVal = (^a: (static member MaxValue : ^a)()) 
     -maxVal 
    | _ -> ... 

この機能はあなたにゼロまたは基になる型の(ネガ/ポジ)の最大値を与えるだろう。

let test (x: int64) = 
    // error FS0001: The type 'int64' does not support the operator 'get_MaxValue' 
    zeroOrMax x 

これは、パラメータが静的メンバ言っていないことを私は静的コンパイルエラーを得続ける、私はMaxValueを実装して自分のタイプを作成するときに見つけ動作しますが、Int32Int64などしながら、静的メンバMaxValueMinValueを持っています

これは、F#がこれらのタイプを特別に扱うためです。あるいは、私は単に異なる構文が必要なだけかもしれません。数値的な一般性を維持しながら、これを回避する方法はありますか?は、基本となる型の最小値/最大値にアクセスしますか?

+5

'int64.MaxValue'は_memberのconstant_、ない_property_です。 –

+0

@fyodor ouch、dejavu、私は以前のことを見たように感じます。些細な回避策はないと思いますか? – Abel

+5

いいえ、方法はありません。 [FsControl](https://github.com/gmpl/FsControl)の[汎用関数](https://github.com/gmpl/FsControl/blob/615f86cbce90596740efdc717cb863a57cefeee4/FsControl.Core/Operators.fs#L397)を作成しました。これは、さまざまな種類のオーバーロードがあります(https://github.com/gmpl/FsControl/blob/615f86cbce90596740efdc717cb863a57cefeee4/FsControl.Core/Numeric.fs#L476)。コードを使用するか、そこにコードをコピーすることができます。 – Gustavo

答えて

2

フィールドは、静的に解決された型メンバー制約のために考慮されません。

コメントに記載されているように、maxValueからFsControlのような汎用関数を作成すると、既知の型ごとにオーバーロードを指定することができます。ここで

this fragment of codeの 'スタンドアロン' バージョンです:

open System 

type MaxValue = MaxValue with 
    static member ($) (_:unit   , _:MaxValue) =() 
    static member ($) (_:bool   , _:MaxValue) = true 
    static member ($) (_:char   , _:MaxValue) = Char.MaxValue 
    static member ($) (_:byte   , _:MaxValue) = Byte.MaxValue 
    static member ($) (_:sbyte   , _:MaxValue) = SByte.MaxValue 
    static member ($) (_:float   , _:MaxValue) = Double.MaxValue 
    static member ($) (_:int16   , _:MaxValue) = Int16.MaxValue 
    static member ($) (_:int   , _:MaxValue) = Int32.MaxValue 
    static member ($) (_:int64   , _:MaxValue) = Int64.MaxValue 
    static member ($) (_:float32  , _:MaxValue) = Single.MaxValue 
    static member ($) (_:uint16  , _:MaxValue) = UInt16.MaxValue 
    static member ($) (_:uint32  , _:MaxValue) = UInt32.MaxValue 
    static member ($) (_:uint64  , _:MaxValue) = UInt64.MaxValue 
    static member ($) (_:decimal  , _:MaxValue) = Decimal.MaxValue 
    static member ($) (_:DateTime  , _:MaxValue) = DateTime.MaxValue 
    static member ($) (_:DateTimeOffset, _:MaxValue) = DateTimeOffset.MaxValue 
    static member ($) (_:TimeSpan  , _:MaxValue) = TimeSpan.MaxValue 

let inline maxValue() :'r = Unchecked.defaultof<'r> $ MaxValue 

type MaxValue with 
    static member inline ($) ((_:'a*'b  ), _:MaxValue) = maxValue(), maxValue() 
    static member inline ($) ((_:'a*'b*'c  ), _:MaxValue) = maxValue(), maxValue(), maxValue() 
    static member inline ($) ((_:'a*'b*'c*'d ), _:MaxValue) = maxValue(), maxValue(), maxValue(), maxValue() 
    static member inline ($) ((_:'a*'b*'c*'d*'e), _:MaxValue) = maxValue(), maxValue(), maxValue(), maxValue(), maxValue() 

// Usage 
let x:int = maxValue() 
// val x : int = 2147483647 

let y:int * float *TimeSpan = maxValue() 
// val y : int * float * TimeSpan = (2147483647, 1.797693135e+308, 10675199.02:48:05.4775807) 
関連する問題