Возвращает различные типы массивов из лямбда-выражения в F#
Вопрос
у меня есть список записей
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
Я возвращаюсь [| Размер 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)
но ему не нравятся два разных типа возвращаемых данных.
Я открыт для предложений по различным (более функциональным?) способам сделать это и был бы признателен за ваш вклад.
Решение
Пользовательский тип варианта - это действительно правильный путь здесь (и, как правило, везде, где вам нужен тип "либо 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 |]
Кстати, есть ли какая-то конкретная причина, по которой вы используете array для возвращаемого типа здесь, а не обычную ленивую последовательность (seq
)?
Другие советы
Вы можете использовать активные шаблоны, чтобы просмотреть ваши данные с нескольких точек зрения:
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;;
Вперед, к пониманию массива гаджетов!
> [| 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
структура данных.