2016-12-16 37 views
1

デバッグの目的で、浮動小数点の詳細は​​printfn "%A"が私に与えているすべてのテストコードが一般化されています。だから、私はboxとタイプにマッチして意味のある出力を得ました。一般化された型を基底の区別された共用体にキャストする場合

ただし、タイプはオプションタイプまたはResult<_, _>タイプ(成功/失敗)です。これらのタイプは、パターンマッチあなたが区別労働組合として扱うが、私は場合、彼らはヒットしません、それらを入力し、テスト:

// Illustrative example of what I'm trying to achieve (I think) 
let rec mkStr v = 
    match box v with 
    | :? double as dbl -> Str.fromFloat dbl 
    | :? int64 as i -> i.ToString() 
    | _ -> 
     match v :> obj with 
     | :? Result<_, _> as res -> // this will never succeed 
      match res with 
      | Success s -> mkStr s 
      | Fail _ -> "Fail" 
     | x -> 
      x.ToString() 

私は、上記のボクシング/アンボクシング/鋳物の様々な試みましたこれらの品種の1つです。私がデバッグすると、Successが通過していることが明確にわかりますが、デバッガではResultと表示されません。 DUの各ディスクリミネータはそれ自体がタイプなので、何が起こっているのか理解していますが、SuccessまたはFailのいずれかと一致するとDUとして扱うようにコンパイラに指示するにはどうすればよいですか?

TLDR:一般化された型が与えられている場合、型がある場合は、どのようにその型を基礎となるDUにテストしキャストできますか?

(PS:私は、これは通常、DUの約進むべき道ではないことを認識し、しかしprintf "%A"が存在しているだけのように、私はこのような状況のように、時折、これは必要とされていると仮定)を取得するために相場を使用して

+3

http://stackoverflow.com/q/3151099/82959、http://stackoverflow.com/q/39875110/82959、およびhttp://stackoverflow.com/q/2140079/82959を参照してください。 – kvb

+0

@kvb、私はすでに再選が必要だと恐れていた。しかし、アクティブなパターンと引用符で、いい解決策です。ありがとう。なぜ私はGoogleでそれを見つけられなかったのか分かりません。 – Abel

答えて

3

ソリューションを@kvbがコメントに載せたパターンマッチングのサポートは素晴らしいトリックです。私は過去に同様の問題を抱えていましたが、反射を使用して値を分解し検査するのではなく、リフレクションを使用して正しいタイプの引数を持つ汎用メソッドを呼び出すことができます。ここでは、最小限の例です:

type MakeString = 
    static member Make<'T>(o:'T) = 
    match box o with 
    | :? float as f -> sprintf "Float: %A" f 
    | o -> 
     if typeof<'T>.Name = "FSharpOption`1" then 
      let tys = typeof<'T>.GetGenericArguments() 
      typeof<MakeString>.GetMethod("MakeOption") 
      .MakeGenericMethod(tys).Invoke(null, [| o |]) :?> string 
     else 
      failwith "Unknown" 

    static member MakeOption<'T>(o:option<'T>) = 
    match o with 
    | None -> "None" 
    | Some v -> "Some " + MakeString.Make(v) 

MakeString.Make(Some 3.14) 

Makeが、我々は静的に知ることができないいくつか'T2用タイプoption<'T2>のある値で呼び出されたとき、私たちはジェネリック型の引数を見て、リフレクションを使用して'T2を見つけ、その後、我々は呼び出しますと'T2をtype引数として使用しています。つまり、MakeOptionの内部には、オプション内に含まれる値の静的型が分かります。

静的型を使用しているので、値がnullと表されている場合はフリーで動作します(したがって、None.GetType()を直接呼び出すと例外がスローされます)。 previous answer posted by @kvbもこれを処理しますが、この場合には特殊なケースを使用します。

+0

kvbが 'null 'をカバーしているように見える、と彼は書いています:_" nullが有効な値であれば特別なケースロジックが必要です(例:Option.None) "。これは良い実行可能なソリューションのように見えます。 '\' 1'はジェネリック型の接尾辞です。 – Abel

+1

_(うわー、私はbacktickの中でバックティックを得ることができなかったことに気づいていませんでした)_ – Abel

+0

あなたとkvbの両方がジェネリック薬によるもので、F#がDUコンクリートタイプを隠しているわけではないと強調しているようです。 – Abel

関連する問題