F# でのさまざまな型の配列の判別共用体から型付き配列を取得する
-
20-09-2019 - |
質問
異なる型の配列の識別結合がある場合、それらを「実際の」型に変換するにはどうすればよいですか?
type ItemStuff =
| Colors of string[]
| Sizes of int[]
let foo = Sizes [|1;2;3|]
上記を実行して foo の値を取得すると、次のようになります。
val foo : ItemStuff = Sizes [|1;2;3|]
foo から実際の int 配列を取得するにはどうすればよいですか?次のようなものにアクセスできる構文が足りないだけですか?foo.[2]
?foo を介して列挙できないため、map を使用できませんでした。返す配列のさまざまな型ごとに適切に型指定された配列を返す ItemStuff のメンバーを作成することもできますが、それは正しくないようです。
ここでの最善のアプローチは何でしょうか?
これが私が最終的にやったことです。より良い方法について何かアイデアはありますか?
type ItemProp =
| Colors of string[]
| Sizes of int[]
| Quants of int[]
member this.GetColors() =
match this with
| Colors (stringArray) ->
stringArray
| _ -> null
member this.GetIntArr() =
match this with
| Sizes (intArray) | Quants (intArray) ->
intArray
|_ -> null
foo.GetIntArr()
解決
私がfooからint型の実際の配列を取得できますか?
foo
がちょうど型ItemStuff
を持っていると言われているので、これは実際の問題です。だから、のは全くSizes
値をに含まれていていない - それは同様Colors
可能性があります。
そこで、あなたのプログラムの開発がここで決定しなければならない。
let getIntArray = function
| Sizes arr -> arr
| Colors _ -> failwith "Given value doesn't contain an int array`
getIntArray foo
は正常に動作しますが、getIntArray (Colors [||])
は失敗しますが、タイプレベルからの両方が有効です。
あなたは、操作が成功することを完全に確信しているならば、あなたはパターンマッチングを直接使用することができます
let getIntArray (Sizes arr) = arr
他のヒント
ItemStuff
は、色や大きさを保持している場合、あなたが知ることができませんので、通常は、パターンマッチングを使用すると思います。あなたは間違いなくあなたがSizes
インスタンスを持っていることがわかっている場合は、あなたのような何かを行うことができます:
let (Sizes arr) = foo
バック配列を引き出してます。
実際にどちらかまたは両方のシナリオ (色またはサイズ) を表現していない場合は、 レコードタイプ ここ:
type ItemStuff =
{ Colors : string[];
Sizes : int[] } with
static member Default = { Colors = [||]; Sizes = [||] }
let foo = { ItemStuff.Default with Sizes = [|1;2;3|] }
printfn "%A" foo.Colors // [||]
printfn "%A" foo.Sizes // [|1; 2; 3|]
printfn "%d" foo.Sizes.[2] // 3
Sizes
なかった場合は、またなしでオプションのタイプを返すことができます。
let getIntArray item =
match item with
| Sizes(i) -> Some(i)
| _ -> None
しかし、関数は常にだけ(画面上に何かを印刷したり、配列にデータを挿入する)副作用を行い、出力データ型、または関数への入力データ型を変換F#で終わりであることに注意してください。
したがって、たとえば、あなただけ(それはSizes
かどうか、何も)Colors
を印刷したい場合には、その目的のために新しい関数を記述するために短くなります:
let printSizes item =
match item with
| Sizes(i) -> printfn "%A" i
| _ -> ()
の代わりに:
let getIntArray item =
match item with
| Sizes(i) -> Some(i)
| _ -> None
let res = getIntArray foo
(function | Some(i) -> printfn "%A" i | _ -> ()) res