Возврат различных типов массивов из лямбда-выражения в F # - PullRequest
1 голос
/ 19 декабря 2009

У меня есть список записей

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

Я хочу, чтобы мой список записей превратился в массив значений, таких как [| "Красный"; "Зеленый"; "Синий" |] или [| 1; 2; 3 |]

Я могу вот так вот добраться

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

но когда я звоню GetProp S itemList, я возвращаюсь [| Size 1; Размер 2; Размер 3 |]. Полезно, но не совсем то, что я ищу.

Я пробовал следующее

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)

но ему не нравятся два разных типа возвращаемых данных.

Я открыт для предложений о различных (более функциональных?) Способах сделать это и был бы признателен за ваш вклад.

Ответы [ 3 ]

5 голосов
/ 19 декабря 2009

Пользовательский вариантный вариант действительно является подходящим вариантом (и, как правило, везде, где вам нужен тип "X или Y"). Однако, как определено, ваша функция выглядит так, как будто она может вернуть массив, в котором смешаны Color и Size, но на практике кажется, что вы хотите, чтобы она возвращала только одно или другое. Если так, это лучше всего отражено в типах:

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 |]

Кстати, есть ли какая-то особая причина, по которой вы используете здесь массив для возвращаемого типа, а не обычную ленивую последовательность (seq)?

4 голосов
/ 19 декабря 2009

Вы можете использовать активные шаблоны для просмотра ваших данных с нескольких точек зрения:

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;;
1 голос
/ 19 декабря 2009

Go go gadget Array Conpretions!

> [| 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"|]

Вам не нужна промежуточная структура данных ItemType или ItemEnum.

...