Comment on page

# Exercise – Making a Card Deck Type

Let's now try to implement a data type that will represent a deck of cards. First, we can think about what type would be fitting for a card deck – a list of cards would be a good representation. But then what type is fitting for a single card? Each card should have a rank and a suit so we can make another type for cards that has the type of a tuple `(Rank, Suit)`. Let's start at the lowest level, the `Rank` and `Suit` type. Remember that we already defined the `Suit` type, but we will now also derive the `Show` class for it:
data Suit = Hearts
| Diamonds
| Clubs
deriving (Show)
which leaves us with the task of defining `Rank` for which we can also use nullary constructors and also derive some built-in classes:
data Rank = Deuce
| Three
| Four
| Five
| Six
| Seven
| Nine
| Ten
| Jack
| Queen
| King
| Ace
deriving (Show, Eq, Ord, Enum)
We can then already use methods of those classes on the `Rank` type:
ghci> Deuce < Three
True
ghci> Deuce <= Three
True
ghci> Deuce == Three
False
ghci> Deuce > Three
False
ghci> [Deuce .. Five]
[Deuce, Three, Four, Five]
We have the `Rank` and `Suit` types now, and we can simply define the type of Card as a type synonym for a tuple of `(Rank, Suit)`:
type Card = (Rank, Suit)
Similarly, we can define a deck of cards as a type synonym for a list of `Card` types:
type Deck = [Card]
We have all the required types for actually building a deck now, so let's make a function for that purpose. We will use list comprehension and take advantage of the fact that `Rank` supports enumeration:
buildDeck :: Deck
buildDeck = [(rank, suit) | rank <- [Deuce .. Ace], suit <- suitList]
where
suitList = [Hearts, Diamonds, Spades, Clubs]
And we can now build a deck of cards using that function:
ghci> deck = buildDeck
ghci> show deck