Haskell: свойство QuickCheck не проходит тесты с использованием последствий

У меня есть следующее свойство, которое я хочу протестировать с помощью quickcheck:

prop_zip xs ys = length xs == length ys ==> 
    unzip (zip xs ys) == (xs,ys)

Несмотря на то, что кажется логически правильным согласно определению zip и unzip, что это свойство должно быть правильным для списков одинаковой длины, быстрая проверка заканчивается:

*** Gave up! Passed only 49 tests.

Заранее спасибо за любую подсказку или совет!


person David    schedule 10.02.2014    source источник
comment
Quickcheck генерирует два случайных списка для каждого теста. Затем он отбрасывает их, если xs и ys не имеют одинаковой длины. Я подозреваю, что эти два списка почти никогда не бывают одинаковой длины, поэтому почти все сгенерированные тестовые случаи отбрасываются, пока quickcheck не сдастся.   -  person fjh    schedule 10.02.2014


Ответы (1)


Предварительные условия, которые трудно выполнить путем создания случайных тестовых случаев, часто являются плохой идеей в QuickCheck. Вместо этого вы должны осторожно использовать генераторы для создания тестовых случаев, которые автоматически удовлетворяют предварительному условию.

Например, в этом случае вы можете использовать forAll для создания второго списка той же длины, что и первый список:

prop_zip' (xs :: [a]) =
  forAll (vectorOf (length xs) arbitrary) $ \ (ys :: [a]) ->
  unzip (zip xs ys) == (xs, ys)

(Здесь я дополнительно использую ScopedTypeVariables, чтобы определить тип второго списка. Возможно, вы захотите изменить это в соответствии со своими конкретными потребностями.)

person kosmikus    schedule 10.02.2014
comment
Вы можете достичь той же цели с помощью asTypeOf - person Ingo; 10.02.2014
comment
Я думал, что термин length xs == length ys ==> гарантирует, что проверка применяется только к спискам одинаковой длины. - person David; 11.02.2014
comment
Да, это гарантирует. Но он по-прежнему будет случайным образом генерировать два списка, и вероятность того, что два случайно сгенерированных списка имеют одинаковую длину, не очень высока. Вот что заставляет QuickCheck сдаваться. См. также комментарий fjh. - person kosmikus; 11.02.2014