如果我有不同类型数组的区别联合,我怎样才能将它们转换为'实际'类型?
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枚举所以我无法使用地图。我可以为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()
答案 0 :(得分:6)
如何从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
答案 1 :(得分:3)
通常你会使用模式匹配,因为你不知道ItemStuff
是否包含颜色或大小。如果你肯定知道你有Sizes
个实例,你可以这样做:
let (Sizes arr) = foo
将数组拉出来。
答案 2 :(得分:2)
如果您实际上没有表示任何一个/或场景(颜色或大小),请考虑在此处使用Record type:
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
答案 3 :(得分:1)
如果受歧视的联合不是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