1

如果我有不同类型数组的区分联合,我如何将它们转换为它们的“实际”类型?

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()
4

4 回答 4

6

如何从 foo 获取实际的 int 数组?

这是实际的问题,因为foo刚刚据说有 type ItemStuff。所以它根本不必包含Sizes- 值 - 它也可以是 a 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
于 2009-12-21T11:10:33.197 回答
3

通常您会使用模式匹配,因为您不知道是否ItemStuff保存颜色或尺寸。如果您确定自己有一个Sizes实例,则可以执行以下操作:

let (Sizes arr) = foo

将阵列拉出。

于 2009-12-21T14:02:27.600 回答
2

如果您实际上并未表示非此即彼的场景(颜色或大小),请考虑在此处使用记录类型

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
于 2009-12-21T13:49:25.093 回答
1

如果有区别的联合不是Sizes.

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

但请记住,在 F# 的末尾,函数总是将输入数据类型转换为输出数据类型,或者函数只是产生副作用(在屏幕上打印某些内容或将数据插入数组)。

因此,例如,如果您只想打印Sizes(或者如果它是 a 则什么都不打印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
于 2009-12-21T11:49:04.203 回答