I am going through "Haskell programming from first principles" and I found myself writing code in the following fashion over and over:
type IntToInt = Fun Int Int
type TypeIdentity = ConcreteFunctorType Int -> Bool
type TypeComposition = ConcreteFunctorType Int -> IntToInt -> IntToInt -> Bool
checkSomething :: IO ()
checkSomething = hspec $ do
describe "Some functor" $ do
it "identity property" $ do
property $ (functorIdentity :: TypeIdentity)
it "composition property" $ do
property $ (functorComposition :: TypeComposition)
I tried abstracting this but at my level I am not able to figure out a way to make it work
what I would have liked to accomplish was something like this
checkFunctor :: (Functor f) => String -> f a -> IO ()
checkFunctor description f = hspec $ do
describe description $ do
it "identity property" $ do
property $ (functorIdentity :: f a -> TypeIdentity)
it "composition property" $ do
property $ ( functorComposition :: f a -> TypeComposition)
EDIT: After Sapanoia's answer I tried as follows
type TypeIdentity = Bool
type TypeComposition = Fun Int Int -> Fun Int Int -> Bool
checkFunctor :: forall f a. (Functor f) => String -> f a -> IO ()
checkFunctor description f = hspec $ do
describe description $ do
it "identity property" $ do
property $ (functorIdentity :: f a -> TypeIdentity)
it "composition property" $ do
property $ (functorCompose' :: f a -> TypeComposition)
but I get the following error
FunctorCheck.hs:22:25: error:
• Couldn't match type ‘a’ with ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
checkFunctor :: forall (f :: * -> *) a.
Functor f =>
String -> f a -> IO ()
at FunctorCheck.hs:16:26
Expected type: f a -> TypeComposition
Actual type: f Int -> Fun Int Int -> Fun Int Int -> Bool
It then becomes quite complicated for me to define the types to generate the arbitrary values and functions.
Is there a way I can bind the type of checkFunctor to a specific type like the following?
checkFuntor :: checkFunctor :: forall f Int. (Functor f) => String -> f a -> IO ()
of course I tried this and it gives me a parse error, I assume it's just me not using 'forall' correctly.