I'm currently learning Haskell from the ever awesome Haskell from first principles, and while trying to check the functor instances for each datatype using QuickCheck, I've stumbled against a mayor problem creating a Function
instance for my Four
datatype:
data Four' a b = Four' a a a b deriving (Eq,Show)
instance Function (Four' a b) where
function = let
injection :: (Function a, Function b) => (Four' a b) -> (a,a,a,b)
injection (Four' x1 x2 x3 z1) = (x1,x2,x3,z1)
surjection :: (Function a, Function b) => (a,a,a,b) -> (Four' a b)
surjection (x1,x2,x3,z1) = (Four' x1 x2 x3 z1)
in functionMap injection surjection
which throws the following error:
Error: • No instance for (Function a) arising from a use of ‘functionMap’
Possible fix:
add (Function a) to the context of
the type signature for:
function :: forall b1. (Four' a b -> b1) -> Four' a b :-> b1
or the instance declaration
• In the expression: functionMap injection surjection
Also, what is exactly the difference between trying to create a Function
instance and an Arbitrary
instance if they both generate functions?
I have some doubts that's really what you want. Some explanation of what you are trying to do which requires Function
would help us tell whether that's the case.
But to answer the technical question that's already there, Function
(and CoArbitrary
, which you will also need if you actually need Function
) have default, generic implementations, so you don't need to do or understand any of it.
Generic
Function
and CoArbitrary
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
import Test.QuickCheck
data Four a b = ... deriving (Eq, Show, Generic) -- Derive generic
-- Default implementations
instance (Function a, Function b) => Function (Four a b)
instance (CoArbitrary a, CoArbitrary b) => CoArbitrary (Four a b)
Also,what is exactly the difference between trying to create a Function instance and an arbitrary instance if they both generate functions?
Arbitrary a
: "how to generate and shrink values of type a
"CoArbitrary a
+Function a
: "how to generate and shrink values of type a -> b
(for suitably constrained b
)"These are not the same.