Пользовательский тестируемый экземпляр с QuickCheck

У меня есть настраиваемая монада результатов / ошибок, ничего особенного:

import Control.Monad (liftM, ap)

data MyResult a = Error String | Success a

instance Functor MyResult where
    fmap = liftM

instance Applicative MyResult where
    pure  = return
    (<*>) = ap

instance Monad MyResult where
    (Error   s) >>= f = Error s
    (Success a) >>= f = f a
    return = Success

Я хочу, чтобы значения в этой монаде создавали экземпляр класса Testable QuickCheck, поэтому я могу писать свойства, которые сохраняются (т.е. проходят тесты), когда значение равно Success _, и не удерживаются (например, не проходят тесты), когда значение равно Error _.

Например, я хотел бы написать такой тест:

myProp :: Property
myProp = forAll (arbitrary :: Int)
    (\x -> if x == 0 then Error "0 not allowed" else Success ())

и пусть String в Error будет сообщением об ошибке теста, если тест не пройден.

Я предполагаю, что мне нужно создать экземпляр Testable для MyResult:

instance Testable t => Testable (MyResult t) where
    property (Success _) = undefined -- what goes here?
    property (Error   s) = undefined -- what goes here?

Однако я не могу понять, как мне реализовать функцию property в Testable, несмотря на то, что я прочитал документация QuickCheck и соответствующий исходный код.

Любая помощь здесь приветствуется.


person AlexJ136    schedule 16.12.2016    source источник


Ответы (1)


Вам нужно сделать Property из вашего результата. Самый простой способ сделать это

property (Success _) = property True
property (Error _)   = property False

Вы также можете преобразовать свой Error результат в Quickcheck Result

property (Error s)   = property $ failed { reason = s }

См. https://hackage.haskell.org/package/QuickCheck-2.9.2/docs/src/Test-QuickCheck-Property.html для определения failed.

person Ingo    schedule 16.12.2016
comment
Могу ли я добавить что-нибудь еще для Error, которое передаст сообщение об ошибке в QuickCheck? - person AlexJ136; 16.12.2016
comment
Конечно, вы также можете использовать тип данных Result, например. property $ MkResult ... - person Ingo; 16.12.2016
comment
Как именно это сделать? Я узнал MkResult из источника quickcheck, но не могу найти никакой информации о том, как его использовать. - person AlexJ136; 16.12.2016
comment
@ AlexJ136 см. Мое приложение - person Ingo; 16.12.2016