module L01B where import Test.QuickCheck -- Datatypes -- David Sands -- 2017-09-01 -- Example of a datatype definition: -- data Bool = True | False -- The Suit (An example of an enumeration type) data Suit = Hearts | Diamonds | Clubs | Spades deriving (Eq,Show) -- Concept [c] Show -- Colour data Colour = Red | Black deriving (Eq,Show) -- colour (Eq) colour :: Suit -> Colour {- colour s | s == Hearts = Red | s == Diamonds = Red | otherwise = Black -} -- Preferable to use Pattern matching colour Hearts = Red colour Diamonds = Red colour _ = Black -- Rank: a datatype for the rank of a card data Rank = Numeric Int | Jack | Queen | King | Ace deriving (Eq,Show) -- Datatype invariant prop_Rank :: Rank -> Bool prop_Rank (Numeric n) = n > 1 && n < 11 prop_Rank _ = True -- rank1 `rankBeats` rank2 ? -- when is one rank higher than another? -- "longhand" definition in the slides. 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 prop_rankBeats r1 r2 = r1 `rankBeats` r2 || r2 `rankBeats` r1 || r1==r2 -- Is it correct? -- Card: a data type containing a Rank and a Suit -- and its projection functions data Card = Card Rank Suit deriving (Eq,Show) -------- Lecture ended here 2017--------------- -- example card -- projection functions rank :: Card -> Rank suit :: Card -> Suit -- and shorthand form defining all three -- data Card = Card {rank::Rank, suit::Suit} -- Really useful when there are lots of things e.g. -- data Person = Person [String] String Int Int Int Int -- ... data Person = Person{ firstnames :: [String] , familyname :: String , year :: Int , month :: Int , day :: Int , pnr :: Int } -- cardBeats card1 card2 checks if card1 beats card2 -- w & wo pattern matching -- cardBeats :: Card -> Card -> Bool -- Hand as a type synonym -- type Hand = [Card] -- select -- select all the cards from the hand of the given suit. -- select :: Suit -> Hand -> Hand -- select = ----------------------------------------------- ------------------------------------------------------- -- The quickCheck "magic" we need to get it to generate arbitrary -- elements of our new datatypes: instance Arbitrary Suit where arbitrary = elements [Spades, Hearts, Diamonds, Clubs] instance Arbitrary Rank where arbitrary = oneof $ [ do return c | c <- [Jack,Queen,King,Ace] ] ++ [ do n <- choose (2,10) return (Numeric n) ] {- instance Arbitrary Card where arbitrary = do r <- arbitrary s <- arbitrary return (Card r s) -} -------------------------------------------------------------------------