I'm in the Haskell Book chapter on Applicative
. I am writing the Applicative
instance for ZipList
and I know I overthought it and am changing my approach. My old approach was:
data List a = Nil | Cons a (List a) deriving (Eq, Show)
newtype ZipList' a =
ZipList' (List a)
deriving (Eq, Show)
instance Applicative ZipList' where
pure a = ZipList' (Cons a Nil)
ZipList' Nil <*> _ = ZipList' Nil
_ <*> ZipList' Nil = ZipList' Nil
(ZipList' (Cons a bs)) <*> (ZipList' (Cons a' bs')) = (ZipList' (Cons (a(a')) Nil)) `mappend` (ZipList' bs <*> ZipList' bs')
I get the error:
No instance for (Monoid b) arising from a use of ‘mappend’
Possible fix:
add (Monoid b) to the context of
the type signature for:
(<*>) :: forall a b. ZipList' (a -> b) -> ZipList' a -> ZipList' b
• In the expression:
(ZipList' (Cons (a (a')) Nil))
`mappend` (ZipList' bs <*> ZipList' bs')
In an equation for ‘<*>’:
(ZipList' (Cons a bs)) <*> (ZipList' (Cons a' bs'))
= (ZipList' (Cons (a (a')) Nil))
`mappend` (ZipList' bs <*> ZipList' bs')
In the instance declaration for ‘Applicative ZipList'’
I think this is because the mappend
uses the Monoid
for ZipList
which is:
instance Monoid a => Monoid (ZipList' a) where
mempty = pure mempty
mappend = liftA2 mappend
which places a Monoid
constraint on the a
. In the Applicative
instance I can't add the a
to the class instance without it ceasing to be a proper Applicative
instance definition. I know that the solution is incorrect, but it did make me think "How would I add a Monoid
constraint to the argument to ZipList
in the Applicative
instance?