Joe*_*Dyk 14 haskell quickcheck
-- 3 (find k"th element of a list)
element_at xs x = xs !! x
prop_3a xs x = (x < length xs && x >= 0) ==> element_at xs (x::Int) == (xs !! x::Int)
Run Code Online (Sandbox Code Playgroud)
当prop_3a通过QuickCheck运行时,它会放弃,因为它不会生成足够长的列表.
如何编写生成长度超过随机整数的列表的生成器?
Dan*_*ton 12
哈马尔的答案完全适合这个问题.但为了回答所提出的确切问题,我忍不住调查了一下.我们来使用吧forAll.
prop_bang x = x >= 0 ==> forAll (listLongerThan x) $ \xs ->
element_at xs x == xs !! x
Run Code Online (Sandbox Code Playgroud)
所以现在我们需要一个函数listLongerThan :: Int -> Gen [Int].它需要一个长度x,并产生一个生成器,它将生成长度大于的列表x.
listLongerThan :: Int -> Gen [Int]
listLongerThan x = replicateM (x+1) arbitrary
Run Code Online (Sandbox Code Playgroud)
这很简单:我们只是利用Monad实例Gen.如果你跑quickCheck prop_bang,你会注意到它开始花了很长时间,因为它开始测试荒谬的长列表.让我们限制列表的长度,使其更快一些.此外,现在listLongerThan只生成一个完全x+1长的列表; 让我们再混合一下,再次利用Gen的Monad实例.
prop_bang =
forAll smallNumber $ \x ->
forAll (listLongerThan x) $ \xs ->
element_at xs x == xs !! x
smallNumber :: Gen Int
smallNumber = fmap ((`mod` 100) . abs) arbitrary
listLongerThan :: Int -> Gen [Int]
listLongerThan x = do
y <- fmap (+1) smallNumber -- y > 0
replicateM (x+y) arbitrary
Run Code Online (Sandbox Code Playgroud)
你可以使用sample smallNumber或sample (listLongerThan 3)在ghci中确保它生成正确的东西.
ham*_*mar 10
走另一条路怎么样?首先,我们让QuickCheck选择一个列表,然后我们约束我们允许的索引.这有效,并且不会丢弃任何测试用例.
prop_3a (NonEmpty xs) = forAll (choose (0, length xs - 1)) $ \i ->
element_at xs i == (xs !! i :: Int)
Run Code Online (Sandbox Code Playgroud)
在这里,我使用forAll特定的生成器作为索引,在这种情况下使用choose它从指定范围中选择一个元素,我也使用该NonEmptyList类型来确保我们不尝试索引到空列表.