私はキーがさまざまな形を取るかもしれないマップを持っています(私は "シェイプ"という言葉をゆるやかに使っています)。これを処理するために、私は、判別組合(DU)を作成しました:同じタイプであるが形状が異なるオブジェクトを扱う慣習的な方法は何ですか?
type AuxDataKey =
| OneString of string
| TwoStrings of string * string
| OneStringInt of string * int
| TwoStringsInt of string * string * int
| OneStringTwoInts of string * int * int
| TwoStringsTwoInts of string * string * int * int
type AuxData = Map<AuxDataKey,AuxDataItem>
キーは、この方法で作成することができます。
let key = AuxDataKey.TwoStringsInt("Vol", ticker, count)
情報はオンザ・作成したキーから取得することができますフライ:
let vols = auxData.[AuxDataKey.TwoStringsInt("Vol", ticker, count)]
これは機能しますが、私はかなり煩わしいです。
type StringInt = String of string | Int of int
、その後、マップキーは、このようなオブジェクトのリストもあります
1つの選択肢は、別のDUを作成することです。マップキーのDUを作成する必要はなく、StringInt
DUははるかに簡単です。一方、コンパイラはリストを受け入れることができるため、例えば、最初の要素がIntで、2番目がStringの場合は、AuxDataKey
DUのいずれの場合にも適合しないので、この方法は安全性が低下します。もっと良い選択肢があるかもしれないので、私は実際にこれを試していません。
must
が同じタイプであるが形状が異なるオブジェクトを扱う慣用方法はありますか?
あなたの現在のソリューションについて、まったく気に入らないものは何ですか?あなたは理想的な世界でどのように見えるでしょうか? –
私には大きな苦情はありません。私が新しいケース(例えば、ThreeStringsTwoInts)を考え出すと、私はDUコードを変更しなければならないということです。しかし、それはDUが働く方法であり、それはまた良い面(安全)を持っています。私はその質問の中で一つの選択肢について言及しましたが、私が考え出したより良い選択肢があるかもしれないと思いました。理想的な言葉では、 'OneStringOneInt'を指定することなく' AuxDataKey( "Vol"、3) 'と書くだけです。それを考えてみてください。おそらく、複数のコンストラクタを持つクラスで行うことができます。 – Soldalma
それはまったく慣用的なことではありませんが、オーバーロードされた 'Item'メンバーでIDictionaryを実装するクラスを作ることができると思います。それからあなたは 'auxData。[(" Vol "、ticker、count)]'と言うことができます。正直なところ、私はおそらくキーの種類ごとに別々の 'Map'を持っているでしょう。明らかに、コンパイル時にはどちらを使うべきかを知っています。そして、すべての値(すべての 'Map'sを連結したものの値であることになります)または典型的な' Map.map'(これを適用する必要があります)を取得する必要がある場合は、いくつかのヘルパー関数を追加してください機能をすべてのマップと一緒にマップする) –