Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate specific random string in QuickCheck?

In Haskell's QuickCheck, how to generate a string such that it contains only the characters ‘S’ and ‘C’, and the position of ‘S’ and ‘C’ is random?

For example: "SCCS", "SSSS", "CCCC", "CSSCCS", ""

My use case is this:

I have two functions countCAndS :: String -> (Int, Int) and countCAndS' :: String -> (Int, Int). They have the same type signature. I'd like to write a QuickCheck property such that I can pass the same string to these two different functions and check if the outputs are the same.

like image 835
Leo Zhang Avatar asked Jan 28 '23 08:01

Leo Zhang


2 Answers

Let your property take a list of booleans and convert them to cs and ss.

prop_CountersEqual :: [Bool] -> Bool
prop_CountersEqual bs = countCAndS css == countCAndS' css where
    css = map (\b -> if b then 'C' else 'S') bs

If you need this frequently, you may want to define a new type with a suitable Arbitrary instance.

newtype CAndS = CAndS String
instance Arbitrary CAndS where
    arbitrary = CAndS . map (\b -> if b then 'C' else 'S') <$> arbitrary

Then you can write your properties as e.g.

prop_CountersEqual' :: CAndS -> Bool
prop_CountersEqual' (CAndS css) = countCAndS css == countCAndS' css
like image 102
Daniel Wagner Avatar answered Jan 30 '23 21:01

Daniel Wagner


QuickCheck provides a flurry of combinators for that, it's super easy and very elegant:

prop_CountersEqual = 
  forAll csString $ \s -> countCAndS s == countCAndS' s

csString :: Gen String
csString = listOf $ elements "CS"

It's also trivial to expand your dictionary, should you need it.

like image 45
Regis Kuckaertz Avatar answered Jan 30 '23 21:01

Regis Kuckaertz