Haskell quickcheck-как генерировать только строки для печати

У меня есть набор простых демонстрационных программ, которые кодируют / декодируют строки и хотят создать некоторые quickCheck тесты для них, но ограничить тесты только для печати строк. Использование guard слишком медленно и терпит неудачу из-за слишком большого количества сгенерированных и отклоненных тестовых случаев, поэтому я хочу создать безопасный генератор для этого домена.

ссылки на это, которые я видел, говорят либо (1) Определить свой собственный произвольные экземпляр Char и используйте это для создания только печатаемых символов для строк или (2) для обертывания самих функций в newtype и писать произвольные экземпляр для этого.

но попытка сделать (1) не удается, потому что теперь есть определение для этого в тесте.QuickCheck, и как бы это сделать-создать safeChar генератор для нового типа, а затем снова должен произвести адаптер для проверенных функций? (Раздел книги RWH об этом отмечает, что он устарел в рекомендации этого определения DIY Char.)

попытка сделать (2) кажется, что я могу либо просто добавить защиту к тестовому предложению, которое локализовано и просто (но терпит неудачу), либо написать новую оболочку и связанный генератор, который кажется более беспорядочным.

очевидно, что это просто(!) и все инструменты предоставлены, но может ли кто-нибудь посоветовать, если это правильный анализ, и дать пример того, как лучше всего это сделать?

2 ответов


отправной точкой, безусловно, является genSafeChar генератор, который может иметь тип Gen Char. Например:

genSafeChar :: Gen Char
genSafeChar = elements ['a'..'z']

тогда вы можете построить это в genSafeString генератор, например, с listOf:

genSafeString :: Gen String
genSafeString = listOf genSafeChar

на данный момент у вас есть несколько разумных решений. Либо сделайте newtype обертка для String:

newtype SafeString = SafeString { unwrapSafeString :: String }
    deriving Show

instance Arbitrary SafeString where
    arbitrary = SafeString <$> genSafeString

(в этом случае вы можете просто подставить определение genSafeString)

и вы можете использовать его что-то вроде этого:--14-->

testWibble (SafeString str) = str == str

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

testWibble = forAll genSafeString $ \str -> str == str

в настоящее время QuickCheck есть PrintableString тип, который также имеет экземпляр arbitrary, что означает, что вы можете легко создавать произвольные строки:

arbitraryPrintableString :: Gen String
arbitraryPrintableString = getPrintableString <$> arbitrary