I want to quickcheck on this Sum
type and I wrote the following code:
data Sum a b =
First a
| Second b
deriving (Eq, Show)
instance Functor (Sum a) where
fmap _ (First x) = First x
fmap f (Second y) = Second (f y)
instance Applicative (Sum a) where
pure = Second
First x <*> _ = First x
Second _ <*> First y = First y
Second x <*> Second y = Second (x y)
instance Monad (Sum a) where
return = pure
First x >>= _ = First x
Second x >>= f = f x
instance (Arbitrary a, Arbitrary b) => Arbitrary (Sum a b) where
arbitrary = do
x <- arbitrary
y <- arbitrary
frequency [(1, return $ First x)
,(1, return $ Second y)]
instance (Eq a, Eq b) => EqProp (Sum a b) where (=-=) = eq
main :: IO ()
main = do
let trigger = undefined :: Sum Int Int
quickBatch $ functor trigger
quickBatch $ applicative trigger
quickBatch $ monad trigger
The compiler complains:
src/eithermonad.hs:100:24: error:
• Couldn't match type ‘Int’ with ‘(a0, b0, c0)’
Expected type: Sum Int (a0, b0, c0)
Actual type: Sum Int Int
• In the first argument of ‘functor’, namely ‘trigger’
In the second argument of ‘($)’, namely ‘functor trigger’
In a stmt of a 'do' block: quickBatch $ functor trigger
|
100 | quickBatch $ functor trigger
| ^^^^^^^
src/eithermonad.hs:101:28: error:
• Couldn't match type ‘Int’ with ‘(a1, b1, c1)’
Expected type: Sum Int (a1, b1, c1)
Actual type: Sum Int Int
• In the first argument of ‘applicative’, namely ‘trigger’
In the second argument of ‘($)’, namely ‘applicative trigger’
In a stmt of a 'do' block: quickBatch $ applicative trigger
|
101 | quickBatch $ applicative trigger
| ^^^^^^^
src/eithermonad.hs:102:22: error:
• Couldn't match type ‘Int’ with ‘(a2, b2, c2)’
Expected type: Sum Int (a2, b2, c2)
Actual type: Sum Int Int
• In the first argument of ‘monad’, namely ‘trigger’
In the second argument of ‘($)’, namely ‘monad trigger’
In a stmt of a 'do' block: quickBatch $ monad trigger
|
102 | quickBatch $ monad trigger
| ^^^^^^^
And after I changed to
let trigger = undefined :: Sum (Int, String, Int) (Int, String, Int)
the code can be compiled and the main
function can run.
The question:
What does the trigger of quickBatch
expect? Why I must change the type Int
to something like (Int, String, Int)
to make it compile?
Check out the signatures of functor
, applicative
, and monad
from the checkers package:
functor :: (Functor m, ...) => m (a, b, c) -> TestBatch
applicative
and monad
are similar: they all require the a functor over a triple. You are trying to use trigger::Sum Int Int
. This means m~Sum Int
, but the error is telling you that Int
(the second one) cannot be unified with (a,b,c)
as required by the signature of functor
.