我有以下内容,
type Pos = (Int, Int)
我想生成这种类型的随机值,但有一些限制(两者都必须是0-8)
我想做点什么
instance Arbitrary Pos where
arbitrary = do x <- choose(0,8)
y <- choose(0,8)
return (x,y)
然后在我的测试中使用它来获得有效的职位。
这不会影响我的别名(?)元组
我尝试的其他方法是在我的测试中使用含义来说
prop_my_prop (x,y) = abs x < 9 && abs y < 9 ==> ...
但我认为这很丑陋,理论上它可能会耗尽快速检查(运行超过1000次)。
这是一项任务,所以我只是希望看到一些迹象或如何处理这一点,我不允许改变Pos。
答案 0 :(得分:6)
这不起作用bc我是别名(?)元组
是的,这是正确的。定义新数据类型,您可以拥有一个新实例。
data Pos = Pos Int Int
或
newtype Pos = Pos (Int, Int)
然后你可以使用你喜欢的任何生成器编写自己的任意实例。
答案 1 :(得分:3)
好吧,如果由于某种原因无法将Pos
更改为data
或newtype
,则可以始终执行以下操作:定义包装器
newtype PosA = PosA { unPosA :: Pos } deriving (Eq,Show) -- and whatever else you need!
以及Arbitrary
实例:
instance Arbitrary PosA where
arbitrary = do x <- choose(0,8)
y <- choose(0,8)
return $ PosA (x,y)
最后,重写您要检查的所有命题,以便其类型不再提及Pos
,而只提及PosA
。例如,假设您有一个函数mirror
,并且镜像两次的属性是标识:
mirror :: Pos -> Pos
mirror (x,y) = (y,x)
prop_mirror :: Pos -> Bool
prop_mirror pos = mirror (mirror pos) == pos
然后你需要制作prop_mirror_A
,就像这样(未经测试的代码!)
prop_mirror_A :: PosA -> Bool
prop_mirror_A pos = prop_mirror (unPosA pos)
你要参加比赛了。您可以通过Clever Typeclass Wizardry从prop_mirror
到prop_mirror_A
进行一些“提升”工作,但我现在不打算考虑: - )
(顺便说一下,这是为什么类型同义词通常不是正确的选择的好理由!)
答案 2 :(得分:2)
positionsToTest :: Gen Pos
positionsToTest = do x <- choose (0,8)
y <- choose (0,8)
return (x,y)
prop_myTest = forAll positionsToTest ( \ pos -> myProperty pos )
run_ung quickCheck on prop_myTest应该做你想做的事。