How to Check Functor Laws Using Checkers Library

How to use the checkers library to check 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 (fa, ix) 

I think I need to use the functor function from Test.QuickCheck.Classes

A type:

 functor :: forall mab c. (Functor m, Arbitrary a, Arbitrary b, Arbitrary c, CoArbitrary a, CoArbitrary b, Show (ma), Arbitrary (ma), EqProp (ma), EqProp (mc)) => m (a, b, c) -> TestBatch 

Now m should probably be my parameter analyzer, 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 that the quick test QuickTest is not proof, and I read the discussion in How to check this applicative instance with checkers? (There is no instance for CoArbitrary (check e0 [Char])) . However, if the quick test fails, I know that my Functor instance is broken ...

Edit

I made 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))

The functor type signature does not have the Read instance mentioned, so I can write

 instance Show (Parser a) where show (Parser a) = "Parsers cannot be printed" 

This gives a new error:

 • No instance for (Arbitrary (Parser Int)) arising from a use of 'functor'In the second argument of '($)', namely 

and I think this is a more difficult problem ...

+5
source share

Source: https://habr.com/ru/post/1273508/


All Articles