简体   繁体   中英

Couldn't match type ‘Int’ with ‘(a0, b0, c0)’ — What does the trigger of `quickBatch` expect?

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM