У меня есть настраиваемая монада результатов / ошибок, ничего особенного:
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 и соответствующий исходный код.
Любая помощь здесь приветствуется.