I am getting a very strange error when trying to implement fmap for one of my datatypes: I have a datatype defined as follows:
newtype WarningAccumulator w a = WarningAccumulator (a,[w])
deriving (Show,Eq)
Next I implemented the fmap function as follows:
instance Functor (WarningAccumulator w) where
fmap :: (a -> b) -> WarningAccumulator w a -> WarningAccumulator w b
fmap f (WarningAccumulator (list, value)) = WarningAccumulator(list, f value)
It gives me:
Couldn't match type ‘a’ with ‘b’
Expected: WarningAccumulator w b
Actual: WarningAccumulator w a
It confuses me very much because f value would return type b not a, so I have no idea why this error occurs? Can someone explain to me why and how to fix it?
CodePudding user response:
You are getting confused because your type parameters are in the order w
a
, while your constructor's fields are in the order a
[w]
. You do need the a
type parameter to be last if that's what you want to fmap over, but the constructor's fields may be in any order. If it's not too wrong semantically, you might choose to reorder the fields so that you can remember how they match up to the type parameters. If you do that, your implementation of fmap
will suddenly be correct.
Alternatively, you can leave the field order as it is, and swap the occurrences of list
and value
in your fmap
implementation:
instance Functor (WarningAccumulator w) where
fmap f (WarningAccumulator (value, list)) = WarningAccumulator(f value, list)