从 F# 中不同类型数组的判别并获取类型化数组
-
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
刚才说的有型ItemStuff
这是实际问题。因此,它的不具有的包含Sizes
价值可言 - 它可能是一个Colors
以及
因此您PROGRAMM就到这里决定
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
不隶属于 StackOverflow