使用以下代数数据类型:
data Cons a = Cons a (Cons a) | Empty deriving (Show, Eq)
我写了一个Arbitrary
的实例:
我的理解是为QuickCheck创建Arbitrary
的实例,以了解如何找到插入其Cons Int
的测试。
instance Arbitrary (Cons Int) where
arbitrary = elements [Empty, Cons 10 (Cons 100 (Cons 55 Empty)), Cons 1 Empty]
和一个功能:
makeArbitraryCons :: Gen (Cons Int)
makeArbitraryCons = arbitrary
然后,我写了一个QuickCheck测试:
prop_id_functor_law_int :: Cons Int -> Bool
prop_id_functor_law_int x = fmap id x == id x
它有效:
ghci> quickCheck prop_id_functor_law_int
*** Failed! Falsifiable (after 1 test):
Cons 10 (Cons 100 (Cons 55 Empty))
但是,当我尝试运行以下测试时,它会失败:
second_functor_law_int :: (Int -> Int) -> (Int -> Int) -> Cons Int -> Bool
second_functor_law_int f g x = left == right
where left = fmap (f . g) $ x
right = (fmap f) . (fmap g) $ x
出现此错误:
ghci> quickCheck second_functor_law_int
<interactive>:418:1:
No instance for (Show (Int -> Int))
arising from a use of `quickCheck'
In the expression: quickCheck second_functor_law_int
In an equation for `it': it = quickCheck second_functor_law_int
我的问题是:
Arbritrary
实例定义
数据类型(例如我的Cons a
)?Gen (Cons Int)
- makeArbitraryCons
?quickCheck
second_functor_law_int
进行第二次测试时发生了什么?答案 0 :(得分:1)
1&amp; 2.您可以:定义Arbitrary
实例或创建Gen ...
函数并使用类似forAll
组合器的内容。
有关使用forAll
功能Gen ...
的示例,请参阅this answer。
second_functor_law_int
的签名是:
second_functor_law ::(Int - &gt; Int) - &gt; (Int - &gt; Int) - &gt; Cons Int - &gt;布尔
所以通过运行quickCheck second_functor_law_int
,您要求QuickCheck创建一个随机Int -> Int
函数。 Quickcheck要求其随机生成的参数是可显示的,因此您会收到此错误,因为函数(通常)没有Show
个实例。
根据您拥有的内容,可以使用特定功能quickCheck
和f
来呼叫g
,例如:
quickCheck $ second_functor_law_int_int (+1) (*2)
然后,QuickCheck将只生成随机Cons Int
值。
顺便说一句,为arbitrary
之类的ADT定义Cons
的更好方法是使用sized
。一些例子: