-- 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で実行すると、十分な長さのリストが生成されないため、あきらめます。
ランダムな整数よりも長いリストを生成するジェネレーターを作成するにはどうすればよいですか?
-- 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で実行すると、十分な長さのリストが生成されないため、あきらめます。
ランダムな整数よりも長いリストを生成するジェネレーターを作成するにはどうすればよいですか?
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+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
sample smallNumber
またはをghciで使用sample (listLongerThan 3)
して、正しいものを生成していることを確認できます。
逆に行ってみませんか?最初にQuickCheckにリストを選択させ、次に許可するインデックスを制限します。これは機能し、テストケースを破棄しません。
prop_3a (NonEmpty xs) = forAll (choose (0, length xs - 1)) $ \i ->
element_at xs i == (xs !! i :: Int)
ここではforAll
、インデックスに特定のジェネレーターを使用します。この場合choose
は、指定された範囲から要素を選択するジェネレーターを使用します。また、NonEmptyList
タイプを使用して、空のリストにインデックスを付けようとしないようにします。
これは機能します:
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
するか、リストとインデックスを一緒に生成します。リストを生成してから、の長さに基づいてインデックスを生成します。リスト)。