How to create a specific random string in QuickCheck?

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

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

My usage example:

I have two functions countCAndS :: String -> (Int, Int)and countCAndS' :: String -> (Int, Int). They have the same type signature. I would like to write a QuickCheck property so that I can pass the same line to these two different functions and check if the output matches.

+4
source share
3 answers

QuickCheck provides a flurry of combinators for this, it is very light and very elegant:

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

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

It is also trivial to expand the dictionary if you need it.

+2

cs ss.

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

, Arbitrary.

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

, ,

prop_CountersEqual' :: CAndS -> Bool
prop_CountersEqual' (CAndS css) = countCAndS css == countCAndS' css
+6

:

newtype CAndS = CAndS String
instance Arbitrary CAndS where
  arbitrary = CAndS <$> listOf (elements "CS")

, , 'C' 'S' es :

prop_CountersAddUp :: CAndS -> Bool
prop_CountersAddUp (CAndS css) = length css == cs + ss
  where (cs, ss) = countCAndS css

, 'C' 'S' es ( ), , , , 'C' 'S':

newtype CAndS = CAndS String
instance Arbitrary CAndS where
  arbitrary = CAndS <$> listOf (frequency [ (1, return 'C')
                                          , (1, return 'S')
                                          , (2, arbitrary) ])

:

newtype CAndS = CAndS (String, Int, Int)
instance Arbitrary CAndS where
    arbitrary = CAndS <$> sized (\n -> do
      cs <- choose (0, n)
      let ss = n - cs
      css <- shuffle (replicate cs 'C' ++ replicate ss 'S')
      return (css, cs, ss))

, :

prop_CountersEqual :: CAndS -> Bool
prop_CountersEqual (CAndS (css, cs, ss)) = cs == cs' && ss == ss'
  where (cs', ss') = countCAndS css
0

Source: https://habr.com/ru/post/1695991/


All Articles