Erhalten ein typisierten Array aus einer diskriminieren Vereinigung verschiedenen Typen von Arrays in F #

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

  •  20-09-2019
  •  | 
  •  

Frage

Wenn ich eine diskriminieren Vereinigung verschiedenen Typen von Arrays, wie kann ich sie auf ihre ‚tatsächlichen‘ Typen umwandeln?

type ItemStuff = 
   | Colors of string[]
   | Sizes of int[]

let foo = Sizes [|1;2;3|]

Nach dem Ausführen der oben, wenn ich den Wert von foo erhalte ich sehen:

val foo : ItemStuff = Sizes [|1;2;3|]

Wie kann ich eine tatsächliche Array von int bekommen ist von foo? Fehle ich einige Syntax nur die mir wie der Zugang zu etwas erlaubt foo.[2]? Ich kann nicht durch foo aufzählen, damit ich nicht in der Lage war Karte zu verwenden. Ich kann ein Mitglied für ItemStuff schreiben, dass kehrt ein richtig getippt Array für jede andere Art von Array Ich kehre, aber das ist einfach nicht richtig schien?

Was sind meine besten hier Ansätze?

Hier ist, was ich tun endete. alle Ideen auf, bessere Möglichkeiten, es zu tun?

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()
War es hilfreich?

Lösung

  

Wie kann ich eine tatsächliche Array von int der von foo bekommen?

Das ist das eigentliche Problem, da foo nur sagt, Typ ItemStuff haben. So ist es hat nicht zu enthalten einen Sizes-Wert überhaupt -. Es auch ein Colors sein könnte

Damit Ihr Programm hat hier zu entscheiden,

let getIntArray = function
    | Sizes arr -> arr
    | Colors _  -> failwith "Given value doesn't contain an int array`

getIntArray foo funktioniert ordnungsgemäß aber getIntArray (Colors [||]) fehl, aber von Typ-Ebene beide gültig sind.

Beachten Sie, dass, wenn Sie ganz sicher sind, dass der Vorgang erfolgreich sein, können Sie Pattern-Matching direkt verwenden:

let getIntArray (Sizes arr) = arr

Andere Tipps

Normalerweise würden Sie Pattern-Matching verwenden, da Sie nicht wissen, ob ein ItemStuff Farben oder Größen hält. Wenn Sie auf jeden Fall wissen, dass Sie eine Sizes Instanz haben, können Sie so etwas wie:

let (Sizes arr) = foo

das Array zurück zu ziehen.

Wenn Sie nicht wirklich repräsentieren ein entweder / oder-Szenario (Farben oder Größen), sollten Sie mit einem SATZART hier:

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

Sie können auch eine Option Typen mit None zurück, wenn die diskriminierte Union keine Sizes ist.

let getIntArray item =
    match item with
    | Sizes(i) -> Some(i)
    | _        -> None

Aber denken Sie daran, dass am Ende in F # eine Funktion wandelt immer einen Eingangsdatentyp in einen Ausgangsdatentyp oder eine Funktion macht nur eine Nebenwirkung (Druck etwas auf dem Bildschirm oder Daten in eine Array einfügen).

So zum Beispiel, wenn Sie nur die Sizes drucken möchten (oder nichts, wenn es ein Colors) es wird kürzer sein, um eine neue Funktion zu diesem Zweck zu schreiben:

let printSizes item =
    match item with
    | Sizes(i) -> printfn "%A" i
    | _        -> ()

statt:

let getIntArray item =
    match item with
    | Sizes(i) -> Some(i)
    | _        -> None

let res = getIntArray foo

(function | Some(i) -> printfn "%A" i | _ -> ()) res
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top