创建一个n#34的任意实例;输入"

时间:2014-10-09 13:59:28

标签: haskell testing functional-programming functional-testing quickcheck

我有以下内容,

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。

3 个答案:

答案 0 :(得分:6)

  

这不起作用bc我是别名(?)元组

是的,这是正确的。定义新数据类型,您可以拥有一个新实例。

data Pos = Pos Int Int 

newtype Pos = Pos (Int, Int)

然后你可以使用你喜欢的任何生成器编写自己的任意实例。

答案 1 :(得分:3)

好吧,如果由于某种原因无法将Pos更改为datanewtype,则可以始终执行以下操作:定义包装器

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_mirrorprop_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应该做你想做的事。

相关问题