You can't; Either a
can be a functor because the partial application of Either
has kind * -> *
, but you can't do partial application from the right.
Instead, you might be interested in the Bifunctor
instance of Either
:
instance Bifunctor Either where
bimap f _ (Left a) = Left (f a)
bimap _ g (Right b) = Right (g b)
bimap
takes two functions, one for each of the two types wrapped by Either
.
> bimap (+1) length (Left 3)
Left 4
> bimap (+1) length (Right "hi")
Right 2
There are also first
and second
functions that focus on one or the other type. second
corresponds to the regular fmap
for Either
; first
is the function you are looking for.
> first (+1) (Left 3)
Left 4
> first (+1) (Right 3)
Right 3
> second (+1) (Left 3)
Left 3
> second (+1) (Right 3)
Right 4
(hat tip to @leftaroundabout)
The Control.Arrow
module provides the left
function, which effectively is the same as second
, but with a more descriptive name and a different derivation. Compare their types:
> :t Data.Bifunctor.second
Data.Bifunctor.second :: Bifunctor p => (b -> c) -> p a b -> p a c
> :t Control.Arrow.left
Control.Arrow.left :: ArrowChoice a => a b c -> a (Either b d) (Either c d)
second
is hard-coded to work with functions and can be restricted by p ~ Either
. left
is hard-coded to work with Either
and can be restricted by a ~ (->)
.
Confusingly, Control.Arrow
also provides a second
function which is similar to the Bifunctor
instance for tuples:
> :t Control.Arrow.second
Control.Arrow.second :: Arrow a => a b c -> a (d, b) (d, c)
> Control.Arrow.second (+1) (1,2) == Data.Bifunctor.second (+1) (1,2)
True
data Either b a = Left a | Right b
. – Willem Van OnsemEither
itself is not a functor, only the higher-kinded type resulting from the application ofEither
to an arbitrary type. – chepnerflip
to do what @Willem Van Onsem said? – Agnishom Chattopadhyayeswap :: Either a b -> Either b a
that could bracket the application offmap f
. (leftmap f = eswap . fmap f . eswap
). Are you thinking of something analogous tonewtype Compose f g a = Compose { getCompose :: f (g a) }
, likenewtype Flip f a b = Flip { getFlip :: f b a }
? – chepner