Как избежать дублирования свойств QuickCheck - PullRequest
1 голос
/ 05 октября 2011

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

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

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?

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

Ответы [ 2 ]

6 голосов
/ 05 октября 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)
2 голосов
/ 05 октября 2011

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

Почему бы не написать реквизит, чтобы он занимал список функций, а затем проверять каждую из них? Тогда вы запустите его как 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 работает со списками чего угодно, а не только со списками строк. Но я не на самом деле проверил это, так что я полагаю, у вас была веская причина.)

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

...