我有一个函数rev
,它为三个类型类中的类型返回一些值:
rev :: (Integral a, Show a, Read a) => a -> a
rev = read . reverse . show
我想通过quickcheck测试一些关于它的属性。虽然,我对测试积分类型的负值不感兴趣,因为我在基础库中缺少Integer
类型时使用Natural
。所以我想,让我们采取与产生的价值为负时产生的价值相反的情况,我会没事的:
prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n | n >= 0 = (rev.rev) n == n
| otherwise = let n' = -n in (rev.rev) n' == n'
(测试的属性在这里并不重要 - 特别是它不适用于非常基本的值,我知道这一点,它不是这个问题的主题)
然后我遇到了Positive
修饰符,并认为虽然我的测试现在正在运行,但以更好的方式实现它会很好。所以我试过了:
prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n = (rev.rev) n == n
我必须承认编译时我感到很惊讶。但是在运行测试时会弹出一个错误:
*** Failed! Exception: 'Prelude.read: no parse' (after 1 test):
Positive {getPositive = 1}
所以我想,“mmk,必须将此Positive
事件声明为Read
”的实例。所以我就这样做了,但实际上已经在quickCheck库中声明了实例,因为ghci对我尖叫。
此时我迷路了,因为我找不到好文件(如果有的话)。
任何帮助我理解quickcheck库中修饰符和其他好东西的指针都将不胜感激。
答案 0 :(得分:18)
使用这些修饰符的常用方法是对它们进行模式匹配,例如
prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id (Positive n) = (rev.rev) n == n
这样,n
将具有基础类型。