I'm using hspec and QuickCheck to validate functor laws for instances of Functor. I have functions
functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool
and
functorComposition :: (Functor f, Eq (f c)) => (Fun a b) -> (Fun b c) -> f a -> Bool
I'm then testing these two using blocks of code like this:
testListFunctorness :: IO ()
testListFunctorness =
hspec $ do
describe "list" $ do
it "should obey functor identity" $ do
property (functorIdentity :: [Int] -> Bool)
it "should obey functor composition" $ do
property
(functorComposition :: (Fun Int String) -> (Fun String Int) -> [Int] -> Bool)
The thing is, to test the same properties for a different Functor instance, I need to copy everything except the [Int]
s:
testMaybeFunctorness :: IO ()
testMaybeFunctorness =
hspec $ do
describe "maybe" $ do
it "should obey functor identity" $ do
property (functorIdentity :: Maybe Int -> Bool)
it "should obey functor composition" $ do
property
(functorComposition :: (Fun Int String) -> (Fun String Int) -> Maybe Int -> Bool)
It feels like I should be able to write an expression which is in some way polymorphic over different Functor
instances, but I can't even think how to begin that.
How can I conveniently reuse that block of test logic for multiple different Functor
s?