Is it possible to change the monad type in a monadic sequence?

either, haskell, monads

Solution

It is not possible to do this in a monadic chain.

Note that this isn't really concerned with `Monad` at all: you're not in any way binding a nested monadic action in the `Left` argument or something like that, but you're only transforming the argument itself. It's basically the functor operation `fmap`, but on the Left instead of Right part:

fmap     :: (r->ρ) -> Either l r -> Either l ρ
fmapLeft :: (l->λ) -> Either l r -> Either λ r

A function with that particular signature, surprisingly, doesn't seem to exist. However, this idea of a functor with two covariant arguments is obviously more general than just `Either`, and indeed there's a dedicated class. It has (IMO rather unfortunate naming, clashes with `Arrow`)

Data.Bifunctor.first :: (a -> b) -> p a c -> p b c

which specialises in fact to

first :: (a -> b) -> Either a c -> Either b c

So you can use

f :: (Show a) => (Either a b) -> (Either String b)
f = first show

Problem

I know it's possible to change the wrapped type, so that you can have ``` f :: (a -> m b) g :: (b -> m c) f >>= g :: (a -> m c) ``` but is it possible to change `m`? If `m` is a `MonadError` and is implemented both by an `Either ErrorA` and `Either ErrorB`, can i somehow chain them? Obviously I can't chain them directly, because what would be the type of `Left`? However, I'm in a situation where I end up calling `show` in either case, but I haven't found a better solution than ``` case mightFail1 of Left e -> show e Right v -> either show doStuff mightFail2 ``` which fails to properly use the monadic behavior of stopping at the first error without me having to check explicitly.

Original source