module Work where import Test.QuickCheck -- Data type for suit of a card (spades, hearts, diamonds, clubs) data Suit = Spades | Hearts | Diamonds | Clubs deriving (Eq, Show) -- Data type for colour of a card (black, red) data Colour = Red | Black deriving (Eq, Show) -- Function that returns the color of a card colour :: Suit -> Colour colour Spades = Black colour Hearts = Red colour Diamonds = Red colour Clubs = Black -- Alternative, usually not good style colour' :: Suit -> Colour colour' s | s==Spades || s==Clubs = Black colour' s | otherwise = Red -- Data type for rank of a card (numeric, jack, queen, king, ace) data Rank = Numeric Integer | Jack | Queen | King | Ace deriving (Eq, Show) -- rankBeats rank1 rank2 checks if rank1 beats rank2 rankBeats :: Rank -> Rank -> Bool rankBeats _ Ace = False rankBeats Ace _ = True rankBeats _ King = False rankBeats King _ = True rankBeats _ Queen = False rankBeats Queen _ = True rankBeats _ Jack = False rankBeats Jack _ = True rankBeats (Numeric m) (Numeric n) = m > n -- Property that checks that either r1 beats r2 or vice versa prop_RankBeats r1 r2 = r1 /= r2 ==> rankBeats r1 r2 /= rankBeats r2 r1 -- Data type for card: a rank and a suit data Card = Card Rank Suit deriving (Eq, Show) rank :: Card -> Rank rank (Card r _) = r suit :: Card -> Suit suit (Card _ s) = s -- Verbose (and bad) version -- rank (Card Jack _) = Jack -- rank (Card Queen _) = Queen -- ... -- Alternative using record syntax data Card' = Card' { rank' :: Rank, suit' :: Suit } deriving (Eq, Show) -- cardBeats card1 card2 checks if card1 beats card2 (same suit and higher rank) -- Data type for a hand of cards data Hand = Empty | Add Card Hand size :: Hand -> Integer size Empty = 0 size (Add c rest) = 1 + size rest instance Arbitrary Rank where arbitrary = oneof $ [ do return c | c <- [Jack,Queen,King,Ace] ] ++ [ do n <- choose (2,10) return (Numeric n) ] shrink Ace = [King] shrink King = [Queen] shrink Queen = [Jack] shrink Jack = [Numeric 10] shrink (Numeric n) = [Numeric n' | n' <- shrink n, 2<=n']