38

F#で識別された共用体の可能な「値」をどのように列挙できますか?

Enum.GetValues(Type)識別された共用体のようなものがあるかどうかを知りたいのですが、どのような種類のデータを列挙するかはわかりません。オプションごとに1つの項目を含む、識別された共用体のリストまたは配列を生成したいと思います。

4

4 に答える 4

45

はい、F#には、.NETのリフレクションの上に独自のリフレクションレイヤーが構築されており、ユニオンの識別など、F#に固有のタイプを理解するのに役立ちます。組合の事例を列挙できるようにするコードは次のとおりです。

open Microsoft.FSharp.Reflection

type MyDU =
    | One
    | Two
    | Three

let cases = FSharpType.GetUnionCases typeof<MyDU>

for case in cases do printfn "%s" case.Name
于 2011-08-09T13:49:34.550 に答える
11

Robertの例を少し拡張すると、識別された共用体のインスタンスがない場合でも、F#リフレクションを使用して、に関する情報(個々のケースの引数のなど)を取得できます。以下は、Robertのサンプルを拡張したものであり、引数のタイプも出力します。

open Microsoft.FSharp.Reflection

let ty = typeof<option<int>>
let cases = FSharpType.GetUnionCases ty

printfn "type %s =" ty.FullName
for case in cases do 
  printf "| %s" case.Name 
  let fields = case.GetFields()
  if fields.Length > 0 then
    printf " of"
  for fld in fields do
    printf " %s " fld.PropertyType.FullName
  printfn ""

たとえば、option<int>typeの場合、次のようになります(出力を少し簡略化しました)。

type Microsoft.FSharp.Core.FSharpOption`1[System.Int32] =
  | None
  | Some of System.Int32

この情報には多くの興味深い用途があります。たとえば、F#ユニオンからDBスキーマを生成したり、XMLを識別されたユニオン(構造を記述する)に解析する関数を作成したりできます。今年初めのGOTOカンファレンスでXML処理のサンプルについて話しました。

于 2011-08-09T14:14:34.283 に答える
11

識別された共用体が単純な識別子のみで構成されている場合(データを格納する場合はありません。これが必要な場合があります:要点

open Microsoft.FSharp.Reflection

module SimpleUnionCaseInfoReflection =

  // will crash if 'T contains members which aren't only tags
  let Construct<'T> (caseInfo: UnionCaseInfo)                   = FSharpValue.MakeUnion(caseInfo, [||]) :?> 'T

  let GetUnionCaseInfoAndInstance<'T> (caseInfo: UnionCaseInfo) = (caseInfo, Construct<'T> caseInfo)

  let AllCases<'T> = 
    FSharpType.GetUnionCases(typeof<'T>)
    |> Seq.map GetUnionCaseInfoAndInstance<'T>
#load "SimpleUnionCaseInfoReflection.fs"

type Foos = Foo | Bar | Baz
SimpleUnionCaseInfoReflection.AllCases<Foos> |> Seq.iter (fun (caseInfo, instance) ->printfn "name: %s instance: %O is Bar? : %b" caseInfo.Name instance (instance.Equals(Foos.Bar)))

(*
> name: Foo instance: FSI_0055+Foos is Bar? : false
> name: Bar instance: FSI_0055+Foos is Bar? : true
> name: Baz instance: FSI_0055+Foos is Bar? : false
*)
于 2015-02-11T23:16:02.790 に答える
2

差別組合は価値観を持っている可能性があるため、インスタンスがなくてもこれがどのように機能するかを理解するのは困難です。

たとえば、次のようなタイプの場合:

type Status = Success of string | Error of System.Exception | Timeout

この場合、成功またはエラーのために配列に含めるものを除いて何をしますか?

于 2011-08-09T13:47:12.120 に答える