We can ask GHCi for information about Ord.
:info Ord
This shows the class definition, followed by a list of instances.
type Ord :: * -> Constraint
class Eq a => Ord a where
  compare :: a -> a -> Ordering
  (<) :: a -> a -> Bool
  (<=) :: a -> a -> Bool
  (>) :: a -> a -> Bool
  (>=) :: a -> a -> Bool
  max :: a -> a -> a
  min :: a -> a -> a
  {-# MINIMAL compare | (<=) #-}
    -- Defined in ‘GHC.Classes’
Its superclass is Eq, and :info Eq tells us:
type Eq :: * -> Constraint
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
  {-# MINIMAL (==) | (/=) #-}
    -- Defined in ‘GHC.Classes’
So in order to implement Ord for Card, we need two things:
- An 
instance Ord Card, with a definition of compare or (<=) 
- An 
instance Eq Card with a definition of (==) or (/=) 
Since these instances are very mechanical to write, normally we ask the compiler to derive them automatically:
data Suit = Diamond | Heart | Spade | Club
  deriving (Eq, Ord)
data Rank = Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
  deriving (Eq, Ord)
data Card = Card Suit Rank
  deriving (Eq, Ord)
If you pass the -ddump-deriv flag to GHC, or use :set -ddump-deriv in GHCi, it will print out the code that it generates for these instances.
However, the task is to understand how to implement these instances by hand, so let’s go through it step by step.
We’ll start with Eq. For Suit and Rank, we need to specify that each constructor is equal to itself (a.k.a. reflexivity) and all other constructors are unequal.
instance Eq Suit where
  Diamond == Diamond  = True
  Heart   == Heart    = True
  Spade   == Spade    = True
  Club    == Club     = True
  _       == _        = False
instance Eq Rank where
  Seven == Seven  = True
  Eight == Eight  = True
  Nine  == Nine   = True
  Ten   == Ten    = True
  Jack  == Jack   = True
  Queen == Queen  = True
  King  == King   = True
  Ace   == Ace    = True
  _     == _      = False
With that out of the way, we can define == for Card in a similar way, by pattern-matching on values of the form Card suit rank.
instance Eq Card where
  -- Two cards are equal if…
  Card suit1 rank1 == Card suit2 rank2
    -- …their suits are equal,
    -- and their ranks are equal.
    = …
There are two conventional ways to define the body. One is spelling it out literally: suit1 == suit2 && rank1 == rank2. Another is to use tuples: (suit1, rank1) == (suit2, rank2).
Again, to define Ord, we can begin with the instances for the enumerations Suit and Rank. We have two choices of how to specify these: (<=) or compare. The direct option is to just list out the table of possible cases, abbreviating cases where we can:
instance Ord Suit where
  Diamond <= _        = True
  Heart   <= Diamond  = False
  Heart   <= _        = True
  Spade   <= Diamond  = False
  Spade   <= Heart    = False
  Spade   <= _        = True
  Club    <= Club     = True
  Club    <= _        = False
instance Ord Rank where
  …
For Card, we now just need to follow the same basic form as for Eq. Since we defined (<=) for Suit and Rank, note that we automatically get a default implementation of the other comparison functions like compare and (<) for those types.
instance Ord Card where
  -- Two cards are in order if…
  Card suit1 rank1 <= Card suit2 rank2
    -- …one rank is less than the other,
    -- or their ranks are equal and suits are in order.
    = …
Again you can translate this comment verbatim using (<), (||), (==), (&&), (<=).
Try implementing these instances based on compare instead of (<=). Hint: use comparing and instance Monoid Ordering from Data.Ord.
Add deriving (Enum) to Rank and Suit—try using fromEnum to simplify their Eq and Ord definitions.