我可以生成任意字符串,并避免在QuickCheck中重复规范吗?

时间:2015-11-11 21:04:35

标签: haskell quickcheck

给出

data MyType = MyType ...

makeMyType :: String -> String -> String -> MyType
-- ...

type StringThing = String

makeMyType期望的字符串(分别):

  • -一些自定义字符串的分隔字符串(例如"Hilary-Jeb-David-Charles"),
  • 一串4个大写字母,
  • 一个.分隔的1到26之间的整数字符串,每个字符用0到2个字符填充(例如"04.23.11.09"

我可以使用QuickCheck生成适当的测试用例,例如

{-# 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 = ...

但是StringThing确实应该在某个范围内采用随机长度的任意大写字母串,并且对所有w... s,c.. s重复相同的规范,以及r....似乎没必要。

QuickCheck中有没有办法:

  1. 生成长度在某些范围内的随机字符串,限制为某些字符,
  2. 使用多个值中的elementschoose“共享”规范?

1 个答案:

答案 0 :(得分:4)

是。 Haskell非常善于将事情分解出来!您当然可以命名和共享子表达式,例如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

对于你的MyType,你也可以使用replicateM:

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]))