Q: Reading a custom data type with error Prelude.read: no parse I am extremely new to functional programming and I have few custom data types of the following to represent a deck of cards.
Data type for Suit
data Suit = Spade | Club | Diamond | Heart
  deriving (Eq, Ord, Enum, Bounded)

instance Show Suit where
  show Spade = "S"
  show Club = "C"
  show Diamond = "D"
  show Heart = "H"

instance Read Suit where
  readsPrec _ [] = []
  readsPrec _ (s: str) = case s of
    'S' -> [(Spade, str)]
    'C' -> [(Club, str)]
    'D' -> [(Diamond, str)]
    'H' -> [(Heart, str)]
    _ -> []

Data type for Rank
data Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
          | Jack | Queen | King | Ace
  deriving (Eq, Ord, Enum, Bounded)

instance Show Rank where
  show Ace = "A"
  show King = "K"
  show Queen = "Q"
  show Jack = "J"
  show rank = show $ fromEnum rank + 2

instance Read Rank where
  readsPrec _ [] = []
  readsPrec _ (s: str) = case s of
      'A' -> [(Ace, str)]
      'K' -> [(King, str)]
      'Q' -> [(Queen, str)]
      'J' -> [(Jack, str)]
      _   -> readNum
    where
      readNum
        | s >= '2' && s <= '9' = [(toEnum (ord s - ord '2') :: Rank, str)]
        | s == '1' = readZero str -- Read a following 0
        | otherwise = []
      readZero ('0': rest) = [(Ten, rest)]
      readZero _ = []

Data type for Card
data Card = Card Suit Rank
  deriving (Eq)

instance Show Card where
  show (Card suit rank) = show suit ++ show rank

instance Read Card where
  readsPrec _ str = do
     (s, rest) <- reads str
     (r, end) <- reads rest
     return (Card s r, end)

When I typed read "S3H5" :: Card in my stack ghci console, it shows an exception error of *** Exception: Prelude.read: no parse. 
May I ask how to fix this?
I have a string of Card information, for instance, "S3HA" which represents two Cards:


*

*Spade Three

*Heart Ace


What I am trying to achieve:
When I read the string of "S3HA", I want the output to be an array of
[Card Spade Three, Card Heart Ace]
Please advise! I am relatively new to Haskell functional programming!
And I do not want to modify the source code for the custom data type of Card, Suit and Rank above but utilizing those data types to create an array of [Card]. Could anyone provide ways to parse a string into a [Card]?

A: As @chi says in the comments to the question, the most straightforward way to achieve your aim is to define the readList method for Card.

For lists, I think you need to redefine the readList method in your Read Card instance. If you do that then the predefined instance Read a => Read [a] will automagically call your own readList, and everything should work.

One possible definition:
instance Read Card where
  ...

  readList str = do
      (card, rest) <- reads str
      if null rest then return ([card], "")
          else fmap (Data.Bifunctor.bimap (card:) id) (readList rest

Or maybe:
import Text.ParserCombinators.ReadP

...

instance Read Card where
  ...

  readList = readP_to_S (many (readS_to_P reads))

 
However, note also that a default Show and Read instance has some advantages:


*

*It is usual — that is, people will know what to expect. With a custom instance, it is necessary to inspect the instance definition in order to use it correctly, while a default instance can be used immediately and effortlessly (except for a lot of typing).

*It is automatically generated — so it is unlikely there to be errors. It gives you a solid ground to stand on, for free, while a custom definition needs to be thoroughly checked if you want to ship the code in good faith.


Therefore, it may be more reasonable to put the same code into monomorphic functions, like say parseCard, parseCards, renderCard and renderCards, and have the best of both worlds.
 
Actually, I think custom Read instances are an obscure corner of Haskell. When I was researching for a similar problem a while ago, I could not find any guides on this subject. (Compare with the abundance of guides on, say, cellular automata or free monads.) This is maybe because people mostly live with the default derived instances until they really need to parse a lot of data, which is when advanced parsing libraries, such as parsec, come into play.
