F# でのさまざまな型の配列の判別共用体から型付き配列を取得する

StackOverflow https://stackoverflow.com/questions/1939113

  •  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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top