Given
data MyType = MyType ...
makeMyType :: String -> String -> String -> MyType
-- ...
type StringThing = String
where the strings that makeMyType
expects are (respectively):
-
delimited string of some custom strings (e.g., "Hilary-Jeb-David-Charles"
),.
delimited string of integers between 1 and 26, each padded with a zero to two characters (e.g., "04.23.11.09"
)I can use QuickCheck to generate adequate test cases with something like
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
import Test.QuickCheck
import Data.List (intercalate)
import Text.Printf (printf)
-- This really should be an arbitrary string of random length in some range
instance Arbitrary StringThing where
arbitrary = elements ["FUSHFJSHF","KLSJDHFLSKJDHFLSKJDFHLSKJDHFLSKJOIWURURW","GHSHDHUUUHHHA"]
instance Arbitrary MyType where
arbitrary = do
-- This repetition feels unnecessary
w1 <- elements ['A'..'Z']
w2 <- elements ['A'..'Z']
w3 <- elements ['A'..'Z']
w4 <- elements ['A'..'Z']
c1 <- elements someListOfCustomStuff
c2 <- elements someListOfCustomStuff
c3 <- elements someListOfCustomStuff
c4 <- elements someListOfCustomStuff
r1 <- choose (1,26)
r2 <- choose (1,26)
r3 <- choose (1,26)
r4 <- choose (1,26)
return $ makeMyType (intercalate "-" [c4,c3,c2,c1])
[w1,w2,w3,w4]
(intercalate "." $ (printf "%02d") <$> ([r1,r2,r3,r4] :: [Int]))
prop_SomeProp :: MyType -> StringThing -> Bool
prop_SomeProp mt st = ...
But StringThing
really should take on arbitrary strings of capital letters of random length within some range, and the repetition of the same specification for all the w...
s, c..
s, and r....
s seems unnecessary.
Is there a way in QuickCheck to:
elements
or choose
among multiple values?Yes. Haskell is great at being able to factor things out! You can certainly name and share subexpressions like elements ['A'..'Z']
capitals = elements ['A'..'Z']
instance Arbitrary StringThing where
arbitrary = do
l <- choose (1,50) -- this is your string length
replicateM l capitals
And for your MyType, you can also use replicateM quite a lot:
instance Arbitrary MyType where
arbitrary = do
ws <- replicateM 4 capitals
cs <- replicateM 4 (elements someListOfCustomStuff)
rs <- replicateM 4 (choose (1,26))
return $ makeMyType (intercalate "-" cs)
ws
(intercalate "." $ (printf "%02d") <$> (rs :: [Int]))