Returning different types of arrays from a lambda expression in F#

做~自己de王妃 提交于 2019-12-11 05:14:34

问题


i have a List of records

type Item = { Color : string; Size : int}
let itemList = [{Color="Red"; Size=1};
                {Color="Green"; Size=2};
                {Color="Blue"; Size=3};]

I am looking to get turn my list of records into an array of values like [|"Red";"Green";"Blue"|] or [|1;2;3|]

I can sorta get there like this

type ItemType =
| Color of string
| Size of int

type ItemEnum =
| C
| S

let GetProp x y =
match x with
| C -> List.toArray y |> Array.map(fun x -> ItemType.Color(x.Color))
| S -> List.toArray y |> Array.map(fun x -> ItemType.Size(x.Size))

but when I call GetProp S itemList I get back [|Size 1; Size 2; Size 3|]. Useful but not exactly what I'm looking for.

I've tried the following

let GetProp2 x y : 'a[] =
match x with
| Color -> List.toArray y |> Array.map(fun x -> x.Color)
| Size -> List.toArray y |> Array.map(fun x -> x.Size)

but it doesn't like the two different return types.

I'm open to suggestions on different (more functional?) ways of doing this and would appreciate your input.


回答1:


A custom variant type is indeed the way to go here (and generally wherever you need a type that is "either X or Y"). However, as defined, your function looks like it might return an array in which Color and Size are mixed, but in practice it seems that you only want it to return one or the other. If so, this is best reflected in the types:

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

let GetProp x ys =
match x with
| C -> Colors [| for y in ys -> y.Color |]
| S -> Sizes [| for y in ys -> y.Size |]

By the way, is there any particular reason why you use array for return type here, rather than the usual lazy sequence (seq)?




回答2:


You can use active patterns to see your data form few points of view:

let (|AsColor|) (v: Item list) = [| for i in v -> i.Color |];;

let (|AsSize|) (v: Item list) = [| for i in v -> i.Size |];;

match itemList,itemList with
  |AsColor ca, AsSize sa -> printfn "%A; %A" ca sa;;



回答3:


Go go gadget Array Comprehensions!

> [| for a in itemList do yield a.Size |];;
val it : int [] = [|1; 2; 3|]
> [| for a in itemList do yield a.Color |];;
val it : string [] = [|"Red"; "Green"; "Blue"|]

You don't need an intermediate ItemType or ItemEnum data structure.



来源:https://stackoverflow.com/questions/1932124/returning-different-types-of-arrays-from-a-lambda-expression-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!