module L04A where -------------------------- -- Instructions for -- Test Data Generation -- Lecture 4A, 2018 -------------------------- import Test.QuickCheck import Data.List(nub) getName = do putStr "Type your name: " name <- getLine putStrLn ("Hi " ++ name ++ "!") return name -- doTwice :: IO t -> IO (t,t) doTwice io = do a <- io b <- io return (a,b) -- types -- * * -- Gen a -- sample, sample' -- arbitrary -- writing generators -- using return, do -- natural numbers nats :: Gen Integer nats = do i <- arbitrary return (abs i) evens :: Gen Integer evens = do i <- arbitrary return (i * 2) -- Building Generators: library functions -- listOf, listOf1, vectorOf -- choose (,) -- return -- oneof -- elements -- frequency -- Example: defining vectorOf using sequence --------------------------------------- vectorOf' n = sequence (replicate n arbitrary) -- Example: Lab 2 datatype ------------------------------------------------- data Suit = Spades | Hearts | Diamonds | Clubs deriving (Show,Eq) -- making an instance instance Arbitrary Suit where arbitrary = rSuit rSuit = elements [Spades, Hearts, Diamonds, Clubs] data Rank = Numeric Int | Jack | Queen | King | Ace deriving (Eq,Show) instance Arbitrary Rank where arbitrary = frequency [(4,rRoyal), (9,rNumeric)] rNumeric, rRoyal :: Gen Rank rRoyal = elements [Jack , Queen , King , Ace] rNumeric = do i <- choose (2,10) return (Numeric i) -- datatype invariant; introducing classify (and collect) prop_rank (Numeric n) = n <= 10 && n > 1 prop_rank _ = True data Card = Card Rank Suit deriving Eq instance Show Card where show (Card r s) = show r ++ " of " ++ show s instance Arbitrary Card where arbitrary = do r <- arbitrary s <- arbitrary return (Card r s) -- instance Arbitrary Card where -- arbitrary = do -- -- A hand of cards type Hand = [Card] rHand :: Gen Hand rHand = do cs <- arbitrary return (nub cs) -- instance Arbitrary Hand where ... -- A generator for Hand? ... -- eliminating duplicates (introduce Hoogle) -- How to use a different generator than arbitrary? -- (i) use QuickCheck function forAll -- [not covered here: see documentation] -- (ii) Make a new type from the old with its own generator -- Example: a poker hand (five different cards) data Poker = Poker Hand deriving Show instance Arbitrary Poker where arbitrary = do cs <- vectorOf 5 arbitrary return (Poker cs) -- tricky exercise: generate a poker hand without duplicates -- Example: Tic-Tac-Toe board data TTT = TTT [[Mark]] instance Show TTT where show (TTT rs) = unlines [showRow r | r <- rs] where showRow r = concat [show m | m <- r] instance Arbitrary TTT where arbitrary = do s <- choose (3,5) rs <- vectorOf s (vectorOf s arbitrary) return (TTT rs) -- tricky exercise: generate realistic TTT boards where -- the difference in X and O is at most 1 -- there is at most one winner, i.e., -- you cannot have three X in a row and three O in a row. data Mark = Nought | Cross | Blank deriving Eq instance Show Mark where show Nought = "O" show Cross = "X" show _ = " " instance Arbitrary Mark where arbitrary = elements [Nought , Cross , Blank] exampleTT = TTT [[Cross ,Blank,Nought] ,[Blank ,Cross,Nought] ,[Nought,Blank,Cross ]]: