ответ Хаммара вполне адекватен проблеме.Но ради ответа на поставленный точный вопрос я не мог не заняться расследованиями.Давайте использовать 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
;давайте немного перепутаем, снова используя экземпляр Monad Gen.
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
или sample (listLongerThan 3)
в ghci, чтобы убедиться, что он генерирует правильные вещи.