- What's the category of monads? What are the arrows in that category?
The category where the objects are monads, i.e., types T of kind Type -> Type with Monad instances, and the arrows A -> B are natural transformations between their underlying functors, conventionally represented in Haskell by functions of type forall x. A x -> B x (although strictly speaking parametricity is a stronger condition than naturality).
There’s an implementation of this in the mmorph package.
The initial object in this category is Identity, since for any monad T there’s exactly one natural transformation forall x. Identity x -> T x. Dually, I think the final object is Const ().
- Why are some monad transformers functors on the category of monads (
MaybeT, RWST, etc), but some not (ContT, SelectT)?
A functor in this category would need a lifted fmap:
fmap'
:: forall m n. (Monad m, Monad n)
=> (forall x. m x -> n x) -> forall x. T m x -> T n x
And you can’t implement this in general for ContT and SelectT. I’m not sure precisely why, but it seems to depend on variance: we’re trying to implement a covariant functor, but ContT and SelectT are invariant in their underlying monads, e.g., m occurs both positively and negatively in the (a -> m r) -> m r inside a ContT r m a.
- What good does it do, from a programming perspective, to be a functor on the category of monads? Why should I care as a consumer of the library?
If you have a general way to “run” a monad m in a monad n, you can’t necessarily lift that into ContT or SelectT; you’re stuck with the more restricted mapping operations like these:
mapSelectT :: (m a -> m a) -> SelectT r m a -> SelectT r m a
mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
Where the underlying monad and result type are fixed. So you can’t always freely hoist actions within a stack that uses these transformers.
IO Stringinto aMaybeT IO String, but it's not possible to convert anIO Stringinto aSelectT <whatever type> IO String- user253751Control.Monad.Morphdocs. - duplode