1

obj 型の入力を数値型に検証する必要があるプログラムを作成しています。基本的に、私は関数を書きたいと思っています

validateint   : obj -> int option
validatefloat : obj -> float option
... and so on

たとえば、これ自体は問題ではありません。たとえば、次のようなものがあります。

let validateint x =
    match x with
        | y when y.GetType() = typeof<int>          -> y :?> int                 |> Some
        | y when y.GetType() = typeof<float>        -> y :?> float        |> int |> Some
        | y when y.GetType() = typeof<System.Int16> -> y :?> System.Int16 |> int |> Some
        /// ...more numeric cases
        | _                                         -> None

ただし、validateint の同様のコードを作成した後、次のようなキャスト関数を入力として受け取る関数を除外することを考えました。

let validatenumeric cast x =
    match x with
        | y when y.GetType() = typeof<int>          -> y :?> int          |> cast |> Some
        | y when y.GetType() = typeof<float>        -> y :?> float        |> cast |> Some
        | y when y.GetType() = typeof<System.Int16> -> y :?> System.Int16 |> cast |> Some
        /// ...more numeric cases
        | _                                         -> None

そして定義する

let validateint = validatenumeric int
let validatefloat = validatenumeric float
...

ただし、F# は基本的にキャストの型を int -> 'a と推測し、2 番目以降の一致ケースが正しく型付けされないため、これは機能しません。すべての数値型を浮動小数点数に追加キャストすることで、これを回避できると思いますが、それは醜いハックのように感じます。よりエレガントなソリューションはありますか?

4

3 に答える 3

2

ジェネリック型を使用する必要があります。これを試してください

let validate<'a, 'b> (cast: 'a -> 'b) (x: 'a) =
    try
        cast x |> Some
    with _ -> None

let a = validate int "123"
let b = validate int 1.23
let c = validate float "abc"
let d = validate<obj, decimal> Convert.ToDecimal (null :> obj)
let e = validate<string, DateTime> Convert.ToDateTime "2013-9-21"
于 2013-09-21T03:20:26.300 に答える
0
open System
let validateint =function
  |(x:obj) when x=null->None
  | :? int as i->Some(i)
  | :? float as f->Some(f|>int)
  | :? string as s->Int32.TryParse(s)|>function |true,x->Some(x)|_->None
  //| :? ...
  |_->None
于 2013-09-21T10:00:47.500 に答える