Как использовать модификаторы с Quickcheck (в моем случае положительно)

У меня есть функция rev, которая возвращает некоторое значение для типа, принадлежащего к трем классам типов:

rev :: (Integral a, Show a, Read a) => a -> a
rev = read . reverse . show

Я хотел бы проверить некоторые свойства об этом с помощью quickcheck. Хотя я не заинтересован в тестировании отрицательных значений интегральных типов, потому что я использую Integer из-за отсутствия типа Natural в базовой библиотеке. Итак, я подумал, давайте возьмем значение, противоположное значению, сгенерированному, когда сгенерированное значение отрицательное, и я буду в порядке:

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n | n >= 0    = (rev.rev) n == n
          | otherwise = let n' = -n in (rev.rev) n' == n'

(протестированное свойство здесь не важно - в частности, оно не подходит для очень простых значений, и я знаю об этом, это не является предметом этого вопроса)

Затем я наткнулся на модификатор Positive и подумал, что, хотя мой тест теперь работает, было бы неплохо реализовать его более удобным способом. Итак, я попробовал:

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n = (rev.rev) n == n

Должен признаться, я был удивлен, когда он скомпилировался. Но потом при запуске теста выскочила ошибка:

*** Failed! Exception: 'Prelude.read: no parse' (after 1 test): 
Positive {getPositive = 1}

Итак, я подумал: «Ммм, надо объявить эту Positive штуку экземпляром Read». Я так и сделал, но экземпляр уже объявлен в библиотеке quickCheck, кажется, потому что ghci кричал на меня.

И тут я заблудился, потому что не нашел хорошей документации (если она есть).

Мы будем благодарны за любой указатель, помогающий мне понять модификаторы и другие приятные вещи в библиотеке quickcheck.


person m09    schedule 17.09.2012    source источник
comment
Нет синтаксического анализа, потому что rev (Positive {getPositive = 1}) это read "}1 = evitisoPteg{ evitisoP".   -  person Daniel Wagner    schedule 18.09.2012


Ответы (1)


Обычный способ использования этих модификаторов - сопоставление с ними по образцу, например

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id (Positive n) = (rev.rev) n == n

Таким образом, n будет иметь базовый тип.

person hammar    schedule 17.09.2012
comment
мля даже не подумал это попробовать. Я такой глупый. Спасибо :) - person m09; 18.09.2012