How do I use the checkers library to test the Functor laws of a simple Parser?
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
import qualified Data.ByteString as BS
type Index = Int
newtype Parser a = Parser (BS.ByteString -> Index -> (a, Index))
runParser :: Parser a -> BS.ByteString -> Index -> (a, Index)
runParser (Parser p) = p
instance Functor Parser where
f `fmap` p = Parser $ \bs i ->
let (a, ix) = runParser p bs i
in (f a, ix)
I think I have to use the functor function from Test.QuickCheck.Classes
The type is:
functor :: forall m a b c. (Functor m, Arbitrary a, Arbitrary b, Arbitrary c,
CoArbitrary a, CoArbitrary b, Show (m a), Arbitrary (m a), EqProp (m a), EqProp (m c))
=> m (a, b, c) -> TestBatch
Now m should probably be my Functor Parser, so I need something like
main :: IO ()
main = = quickBatch (functor (Parser (a, b, c))
But what do I use for (a, b, c)
?
Note: I know a quick QuickTest test is not a proof and I have read the discussion in How do I test this applicative instance with checkers? (No instance for CoArbitrary (Validation e0 [Char])) . However if the quick test fails, I know that my Functor instance is broken...
Edit
I made a little progress: I can write
main :: IO ()
main = quickBatch $ functor (undefined :: Parser (Int, String, Char))
This gives an error: No instance for (Show (Parser Int))
In the type signature of functor, there is no Read instance mentioned, so I can write
instance Show (Parser a) where
show (Parser a) = "Parsers cannot be printed"
This the gives a new error:
• No instance for (Arbitrary (Parser Int))
arising from a use of ‘functor’
• In the second argument of ‘($)’, namely
and I guess this is a tougher problem...