Note, this question is not about "monoids in the category of endofunctors". Nor is it directly about
Functor
s (aMonad
is always aFunctor
, but this question is concerned mainly about monad transformers)
The docs on Haskell's SelectT
monad transformer states that
SelectT
is not a functor on the category of monads, and many operations cannot be lifted through it.
MaybeT
, RWST
, etc), but some not (ContT
, SelectT
)?A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.
Functor categories serve as the hom-categories in the strict 2-category Cat. In the context of enriched category theory the functor category is generalized to the enriched functor category.
A Functor is kind of mapping of objects and morphisms that preserves composition and identity. We have two Categories: A and B . In Category A we have two objects a and b with morphism f . Our Functor is a mapping of objects a and b to Fa and Fb and mapping of morphisms, in this case single morphism: f to Ff .
Morphisms in this category are natural transformations between functors. Functors are often defined by universal properties; examples are the tensor product, the direct sum and direct product of groups or vector spaces, construction of free groups and modules, direct and inverse limits.
- 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With