创建“类型”
问题描述:
我有以下,创建“类型”
type Pos = (Int, Int)
我要生成这种类型的随机值有一些限制(这两个必须是0-8)
我会的任意intance喜欢做类似
instance Arbitrary Pos where
arbitrary = do x <- choose(0,8)
y <- choose(0,8)
return (x,y)
然后在我的测试中使用它有有效位置。
BC我走样这是不行的(?)元组
我试图其他方法使用的影响在我的测试说
prop_my_prop (x,y) = abs x < 9 && abs y < 9 ==> ...
,但我认为这是相当丑陋理论上它可能耗尽快速检测(超过1000次)。
这是一项任务,所以我只想要一些指示,看看或如何处理这个问题,我不允许更改Pos。
答
唐斯图尔特的回答描述了可以说最好的方式来做到这一点。但是,如果由于某种原因你不想使用NEWTYPE可以按如下方式使用自定义生成器:
positionsToTest :: Gen Pos
positionsToTest = do x <- choose (0,8)
y <- choose (0,8)
return (x,y)
prop_myTest = forAll positionsToTest (\ pos -> myProperty pos)
Runnung快速检查上prop_myTest应该做你想要什么。
答
BC我走样这是不行的(?)元组
是的,这是正确的。定义一个新的数据类型,你可以有一个新的实例。
data Pos = Pos Int Int
或
newtype Pos = Pos (Int, Int)
然后,你可以写出来与大家喜欢的任何发电机自己的任意实例。
答
好吧,如果你不能改变Pos
到data
或newtype
不管什么原因,你总是可以做到以下几点:与Arbitrary
实例一起定义的包装
newtype PosA = PosA { unPosA :: Pos } deriving (Eq,Show) -- and whatever else you need!
它:
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)
(未经测试的代码!)而你正在参加比赛。你也许可以做一些从prop_mirror
由聪明类型类巫术工作“提升”到prop_mirror_A
的,但我不打算现在想想:-)
(顺便说一句,这是一个很好的理由键入同义词通常不是正确的选择!)
我不允许将类型Pos更改为数据Pos – skyw00lker 2014-10-09 14:10:18
然后您必须将您的生成器编写为函数而不是类型的方法。 – 2014-10-09 14:20:43