A obtenção de uma matriz digitada a partir de um discriminar união de diferentes tipos de matrizes em F#

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

  •  20-09-2019
  •  | 
  •  

Pergunta

Se eu tiver um discriminar união de diferentes tipos de matrizes como posso convertê-los para o seu 'reais' os tipos?

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

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

Depois de executar o acima quando eu recebo o valor do foo eu ver:

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

Como posso obter uma matriz real de int do foo?Será que eu estou faltando alguma sintaxe que me permite o acesso a algo como foo.[2]?Eu não posso enumerar foo, então eu não era capaz de utilizar o mapa.Eu poderia escrever um membro para ItemStuff que retorna uma digitado corretamente matriz para cada tipo diferente de matriz eu estou retornando, mas que simplesmente não parece certo?

Quais são os meus melhores abordagens aqui?

Aqui está o que eu acabei fazendo.todas as idéias sobre as melhores formas de o fazer?

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()
Foi útil?

Solução

Como posso obter uma variedade real de int da Foo?

Esse é o problema real desde foo Diz -se que tem tipo ItemStuff. Então isso não precisa conter a Sizes-VALUE - poderia ser um Colors também.

Portanto, sua programação tem que decidir aqui

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

getIntArray foo vai funcionar corretamente, mas getIntArray (Colors [||]) falhará, mas no nível do tipo, ambos são válidos.

Observe que, se você tiver certeza de que a operação será bem-sucedida, poderá usar a correspondência de padrões diretamente:

let getIntArray (Sizes arr) = arr

Outras dicas

Normalmente você usaria a correspondência de padrões, pois não saberá se um ItemStuff segura cores ou tamanhos. Se você definitivamente sabe que tem um Sizes Por exemplo, você pode fazer algo como:

let (Sizes arr) = foo

Para puxar a matriz de volta.

Se você não está realmente representando um ou cenário (Cores OU Tamanhos), considere o uso de um Tipo de registro aqui:

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

Você também pode devolver um tipo de opção com nenhum se o sindicato discriminado não fosse um Sizes.

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

Mas lembre -se de que, no final da função F#, uma função sempre transforma um tipo de dados de entrada em um tipo de dados de saída, ou uma função apenas faz um efeito colateral (imprimir algo na tela ou inserir dados em uma matriz).

Então, por exemplo, se você apenas quiser imprimir o Sizes (ou nada se for um Colors) será mais curto escrever uma nova função para esse fim:

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

ao invés de:

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

let res = getIntArray foo

(function | Some(i) -> printfn "%A" i | _ -> ()) res
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top