2

私が差別された組合を持っているとしましょう:

type card = Smithy | Cellar | Chapel

そして、判別共用体を何らかの値にマップする関数:

let initialCardCount = function
  Smithy -> 4
  Cellar -> 6
  Chapel -> 2

次のように、組合の各メンバーのコストを含むマップを生成したいと思います。

[(Smithy, 4); (Cellar, 6); (Chapel, 2)]

これは可能ですか?次のようなことができるようになりたいです。

List.zip (allValues f) (List.map getCost (allValues f)) |> Map.ofList

この質問は役に立ちますが、私が必要としているものではありません。プロパティを検査するだけでなく、メモリ内のユニオン メンバーにアクセスできるようにしたいと考えています。

私がこれをやりたい理由は、ゲーム内のすべての異なる種類のカードを表す識別された共用体と、開始時に各カードが何枚あるべきかを示す関数を使用できるようにするためです。その後、イニシャルを簡単に生成できますカードからカウントへのマッピング。これを行うより良い方法はありますか?

4

1 に答える 1

5

F# リフレクションを使用して、可能なすべての判別共用体ケースのリストを取得できますが、リフレクションの欠点を理解することが重要です。注意して使用しないと、簡単に設計が不十分になる可能性があります (よりシンプルでエレガントな関数ソリューションがある場合があります)。また、効率も悪くなります (ただし、すべてのケースのリストを取得する必要があるのは 1 回だけです)。

次のgetAllValues関数はすべてのケースを取得します - どのケースにも値が格納されていないと仮定します (つまり、機能しSmithy of stringません!) ケースに何らかの引数を渡したい場合は、ボックス化された値を の 2 番目の引数に渡す必要がありますMakeUnion

open Microsoft.FSharp.Reflection

let getAllValues<'T>() : 'T list =
  let cases = FSharpType.GetUnionCases(typeof<'T>)
  [ for c in cases -> unbox (FSharpValue.MakeUnion(c, [| |])) ]

シナリオで関数を使用する例を次に示します。

type card = Smithy | Cellar | Chapel 

let initialCardCount = function 
  | Smithy -> 4 
  | Cellar -> 6 
  | Chapel -> 2 

let values = getAllValues<card>()
List.zip values (List.map initialCardCount values)
于 2012-06-03T11:30:14.833 に答える