# All possible combinations of a product type

``````-- Features
type Symbol = Triangle | Circle | Wave
type Shading = Striped | Empty | Solid
type Color = Red | Green | Purple
type Number = One | Two | Three

-- Card
type Card = Card Symbol Shading Color Number

-- Deck
type alias Deck = List Card

-- A deck has 81 cards, which is all the possible combinations to combine
-- the four features in a card. Each card is unique and exists only once in the deck.
-- Now the question: How can I generate the deck?
-- (it does not have to be random (yet)).
-- extending the question: How can I generally generate all possible
-- combinations of a product type?``````
``````deck : Deck
deck =
let
listSymbol = [Triangle,Circle,Wave]
listColor = [Red,Green,Purple]
listNumber = [One,Two,Three]

productApply : List a -> List (a -> b) -> List b
productApply l1 =
List.map (\b -> l1 |> List.map b)
>> List.concat
in
Card
|> List.singleton
|> productApply listSymbol
|> productApply listColor
|> productApply listNumber
``````
1 Like

Hey thanks very much for your reply. Can you explain what productApply does a little, because I am not sure I understand this, well. Thanks!

Well, essentially what you are asking for is called a â€ścartesian productâ€ť (thats the mathematical term for it)

``````product : List a -> List b -> List (a,b)
product l1 l2 =
l2
|> List.map (\b -> l1 |> List.map (\a -> (a,b)))
|> List.concat
``````

with this we would get something like

``````listSymbol
|> product listColor
|> product listNumber
)
``````

This got me thinking. Instead of returning a tuple I could immediately apply the value to the function `Card`.

``````productApply : List a -> List (a->b) -> List b
productApply l1 l2 =
l2
|> List.map (\b -> l1 |> List.map (\a -> b a))
|> List.concat
``````

Note that b is now a function.
At the end I removed `l2` and replaced `(\a -> b a)` with `b` as thatâ€™s essentially the same. This last step is just how I like my code to look like, so you donâ€™t have to do it.

Thanks. So the elements of l2 become b. So for every element b you map a function that takes every elements a from l1 and applies a to b. Then you flatten the result. but where is List (a -> b) coming from? And is List (a->b) a list of functions from a to b?

The constructor function `Card` is of type `Symbol -> Shading -> Color -> Number -> Card`.

So in the first step `Card |> List.singleton` is the `List (a -> b)` where

• `a` equals `Symbol`
• `b` equals `Shading -> Color -> Number -> Card`
1 Like

Possibly easier to read and debug https://ellie-app.com/7pRVnPVm8Z5a1

2 Likes

Another one using List.Extra https://ellie-app.com/7pSvFtsTcP3a1

1 Like

Thank you all. I think I understand now!

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.