Monads get fmap
from Functor
typeclass. Why comonads don't need a cofmap
method defined in a Cofunctor
class?
A contravariant functor F from a category C to a category D is simply a functor from the opposite category Cop to D. To emphasize that one means a functor C→D as stated and not as a functor Cop→D one sometimes says covariant functor when referring to non-contravariant functors, for emphasis.
Most importantly, Fold r is an instance of both Functor and Applicative , so you can map over and combine the results of different folds.
Comonad is a Functor and provides duals of the Monad pure and flatMap functions. A dual to a function has the same types but the direction of the arrows are reversed. Whether or not that is useful, or even possible, depends on the particular type.
Functor
is defined as:
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
Cofunctor
could be defined as follows:
class Cofunctor f where
cofmap :: (b -> a) -> (f b -> f a)
So, both are technically the same, and that's why Cofunctor
does not exist. "The dual concept of 'functor in general' is still 'functor in general'".
Since Functor
and Cofunctor
are the same, both monads and comonads are defined by using Functor
. But don't let that make you think that monads and comonads are the same thing, they're not.
A monad is defined (simplifying) as:
class Functor m => Monad where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
whether a comonad (again, simplified) is:
class Functor w => Comonad where
extract :: w a -> a
extend :: (w a -> b) -> w a -> w b
Note the "symmetry".
Another thing is a contravariant functor, defined as:
import Data.Functor.Contravariant
class Contravariant f where
contramap :: (b -> a) -> (f a -> f b)
For reference,
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
instance Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
join :: Monad m => m (m a) -> m a
Note that given extract
and extend
you can produce fmap
and duplicate
, and that given return
and >>=
you can produce fmap
, pure
, <*>
, and join
. So we can focus on just pure
+>>=
and extract
+extend
.
I imagine you might be looking for something like
class InverseFunctor f where
unmap :: (f a -> f b) -> a -> b
Since the Monad
class makes it easy to "put things in" while only allowing a sort of hypothetical approach to "taking things out", and Comonad
does something opposed to that, your request initially sounds sensible. However, there is a significant asymmetry between >>=
and extend
that will get in the way of any attempt to define unmap
. Note in particular that the first argument of >>=
has type m a
. The second argument of extend
has type w a
—not a
.
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