Как избежать дублирования свойств быстрой проверки

#haskell #quickcheck

#haskell #быстрая проверка

Вопрос:

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

У меня есть следующий код:

импорт теста.быстрая проверка
импорт текста.Printf

main = mapM_ ((s,a) -> printf "%-25s: " s >> a) тесты

-- 1
myLast lst = последний lst
prop_1a xs x = myLast (xs    [x]) == (x::String)

myLast' = head . обратный
prop_1b xs x = myLast' (xs    [x]) == (x::String)

тесты = [("1a", QuickCheck prop_1a)
,("1b", QuickCheck prop_1b)
]

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

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

Комментарии:

1. Пожалуйста, никогда не используйте слово «метод» как синоним «функции»

Ответ №1:

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

 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)
  

Ответ №2:

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

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

редактировать: я боялся, что вы можете спросить, что: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 amp;amp; myProp fs xs x
  

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

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

Комментарии:

1. У меня возникли проблемы с определением синтаксиса для этого — не могли бы вы изменить свой ответ, чтобы показать это?

2. Я добавил x::String, потому что мне нужно было где-то предоставить информацию о типе.