Writing something like this works fine:
data Either a b = Left a | Right b
instance Functor (Either a) where
fmap _ (Left x) = Left x
fmap f (Right x) = Right (f x)
Now lets say I want to invert this, Left applies f to value:
instance Functor (Either a) where
fmap _ (Right x) = Right x
fmap f (Left x) = Left (f x)
This doesn't compile, I suppose I need to have something like Functor (Either _ b)
, how do I do this?
You can't, and you shouldn't. If you could do this, it would make it a lot tougher to know whether
fmap (+1) (Left 1)
should beLeft 1
orLeft 2
.Bifunctor
That said, the abstraction you are looking for (something which can be mapped over on either side) exists and is called a
Bifunctor
. Then, depending on whether you want to map over theLeft
s or theRight
s, you usefirst
orsecond
:Flip
Alternately, if you want to stick to
fmap
only and not be bothered withfirst
andsecond
, you can wrap your data type in theFlip
newtype, which has the effect of looking for the functor instance of the second type variable. You still rely on the fact thatEither
is aBifunctor
, but you avoidfirst
andsecond
: