14
-- 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)

prop_3aをQuickCheckで実行すると、十分な長さのリストが生成されないため、あきらめます。

ランダムな整数よりも長いリストを生成するジェネレーターを作成するにはどうすればよいですか?

4

3 に答える 3

12

hammarの答えは問題に対して完全に適切です。しかし、尋ねられた正確な質問に答えるために、私は少し調査せざるを得ませんでした。を使用しましょうforAll

prop_bang x = x >= 0 ==> forAll (listLongerThan x) $ \xs ->
  element_at xs x == xs !! x

したがって、関数が必要になりますlistLongerThan :: Int -> Gen [Int]。これは長さxを取​​り、。より大きい長さのリストを生成するジェネレーターを生成しますx

listLongerThan :: Int -> Gen [Int]
listLongerThan x = replicateM (x+1) arbitrary

それはかなり簡単です。単純にのMonadインスタンスを利用しますGen。を実行するquickCheck prop_bangと、非常に長いリストのテストが開始されるため、かなり長い時間がかかり始めることに気付くでしょう。リストの長さを制限して、リストを少し速くします。また、現時点では、正確に長いlistLongerThanリストのみが生成されます。x+1Genの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

sample smallNumberまたはをghciで使用sample (listLongerThan 3)して、正しいものを生成していることを確認できます。

于 2011-10-08T03:38:57.190 に答える
10

逆に行ってみませんか?最初にQuickCheckにリストを選択させ、次に許可するインデックスを制限します。これは機能し、テストケースを破棄しません。

prop_3a (NonEmpty xs) = forAll (choose (0, length xs - 1)) $ \i ->
    element_at xs i == (xs !! i :: Int)

ここではforAll、インデックスに特定のジェネレーターを使用します。この場合chooseは、指定された範囲から要素を選択するジェネレーターを使用します。またNonEmptyListタイプを使用して、空のリストにインデックスを付けようとしないようにします。

于 2011-10-08T00:38:31.747 に答える
4

これは機能します:

import Test.QuickCheck

element_at      :: [a] -> Int -> a
element_at xs i = xs !! i

prop_3a      :: [Int] -> Int -> Property
prop_3a xs i = (i >= 0) ==> (length xs > i) ==> element_at xs i == xs !! i

ただし、これに伴う問題は、多くのサンプル値が破棄されることです。Positiveインデックスが有効であることを確認するのに役立つようなものを使用できます。

より複雑にしたい場合は、より多くのnewtypeラッパーを使用して、十分な長さの値を生成しようとすることができます(おそらく、を使用sizedするか、リストとインデックスを一緒に生成します。リストを生成してから、の長さに基づいてインデックスを生成します。リスト)。

于 2011-10-08T00:33:00.047 に答える