Избегайте дублирования свойств QuickCheck

Я начинаю изучать Haskell, решая 99 задач Haskell. http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_Problems Я бы хотел написать тесты для каждой программы / функции с помощью quickcheck.

У меня такой код:

import Test.QuickCheck
import Text.Printf

main  = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests

-- 1
myLast  lst = last lst
prop_1a xs x = myLast  (xs ++ [x]) == (x::String)

myLast' = head . reverse
prop_1b xs x = myLast' (xs ++ [x]) == (x::String)

tests  = [("1a",                 quickCheck prop_1a)
         ,("1b",                 quickCheck prop_1b)
         ]

Я мог бы написать myLast'', myLast''' и т. Д. Есть ли способ протестировать все эти методы без дублирования кода и свойств быстрой проверки?

Связанный вопрос: прямо сейчас я говорю quickcheck использовать Strings. Есть ли способ случайным образом использовать разные типы для тестирования?


person Joe Van Dyk    schedule 05.10.2011    source источник
comment
Пожалуйста, никогда не используйте слово "метод" как синоним функции.   -  person alternative    schedule 06.10.2011


Ответы (2)


Есть ли способ протестировать все эти методы без дублирования кода и свойств быстрой проверки?

Почему бы не написать опору так, чтобы она брала список функций, а затем проверяла каждую из них? Тогда вы запустите его как quickCheck (myProp [myLast, myLast', myLast'']).

edit: Я боялся, что вы спросите, что: P Чтобы сделать это, как я сказал выше, myProp должен взять список функций, все из которых имеют тот же тип, что и last, и вернуть логическое значение:

myProp :: [([a] -> a)] -> Bool

Но теперь, когда я смотрю на это, может быть лучше (и более аналогично вашему исходному подходу), чтобы он также принимал список и элемент, поэтому я думаю, что сделаю это вместо этого:

myProp :: [([a] -> a)] -> [a] -> a -> Bool

Если список пуст, мы возвращаем true:

myProp [] _ _ = True

Если нет, то мы проверяем, выполняется ли свойство для первой функции в списке, а затем рекурсивно проверяем остальную часть списка:

myProp [f:fs] xs x = f (xs ++ [x]) == x && myProp fs xs x

(Я не уверен, почему вы написали x::String в своей реализации. Я не думаю, что вам это нужно - last работает со списками чего угодно, а не только со списками строк. Но я на самом деле не тестировал это, поэтому предполагаю у тебя была веская причина.)

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

person MatrixFrog    schedule 05.10.2011
comment
У меня проблемы с определением синтаксиса для этого - не могли бы вы изменить свой ответ, чтобы это показать? - person Joe Van Dyk; 08.10.2011
comment
Я добавил x :: String, потому что мне нужно было где-то предоставить информацию о типе. - person Joe Van Dyk; 08.10.2011

Просто возьмите функцию для тестирования в качестве другого аргумента:

prop_1 last xs x = last (xs ++ [x]) == (x :: Int)

tests = zipWith mkTest ['a'..] [myLast, myLast']
  where mkTest letter func = ('1':[letter], quickCheck $ prop_1 func)
person hammar    schedule 05.10.2011