Are there contravariant monads?

情到浓时终转凉″ 提交于 2019-11-27 21:34:45

问题


Functors can be covariant and contravariant. Can this covariant/contravariant duality also be applied to monads?

Something like:

class Monad m where
  return :: a -> m a
  (>>=) :: m a -> (a -> m b) -> m b    

class ContraMonad m where
  return :: a -> m a
  contrabind :: m a -> (b -> m a) -> m b

Does ContraMonad class make sense? Any examples?


回答1:


Well, of course, it's possible to define it, but I doubt it would be of any use.

There is a popular saying that "monad is just a monoid in a category of endofunctors". What it means is, first of all, that we have a category of endofunctors (meaning, (covariant) functors from some category to itself), and what's more, we have some multiplication on this endofunctors (in this case — composition). And then monad fits into some general framework that we don't have to worry about right now. The point is, there is no "multiplication" of contravariant functors. Composition of two covariant functors is again a covariant functor; but composition of two contravariant functors is not a contravariant functor (rather it's a covariant functor, so, a totally different beast).

So, "contravariant monads" do not really make sense.




回答2:


A contravariant functor is a functor from one category into its opposite category, i.e. from one category into another (albeit closely related) one. OTOH, a monad is foremostly an endofunctor i.e. from one category into itself. So it can't be contravariant.

This kind of stuff always tends to be a lot clearer when you consider the “fundamental mathematical” definition of monads:

class Functor m => Monad m where
  pure :: a -> m a
  join :: m (m a) -> m a

As you see there aren't really any arrows in there that you could turn around in the result, like you did with contrabind. Of course there is

class Functor n => Comonad n where
  extract :: n a -> a
  duplicate :: n a -> n (n a)

but comonads are still covariant functors.

Unlike monads, applicatives (monoidal functors) needn't be endofunctors, so I believe these can be turned around. Let's start from the “fundamental” definition:

class Functor f => Monoidal f where
  pureUnit :: () -> f ()
  fzipWith :: ((a,b)->c) -> (f a, f b)->f c  -- I avoid currying to make it clear what the arrows are.

(exercise: define a derived Applicative instance in terms of this, and vice versa)

Turning it around

class Contravariant f => ContraApp f where
  pureDisunit :: f () -> ()
  fcontraunzip :: ((a,b)->c) -> f c->(f a, f b)
                            -- I'm not sure, maybe this should
                            -- be `f c -> Either (f a) (f b)` instead.

No idea how useful that would be. pureDisunit is certainly not useful, because its only implementation is always const ().

Let's try writing the obvious instance:

newtype Opp a b = Opp { getOpp :: b -> a }

instance Contravariant (Opp a) where
  contramap f (Opp g) = Opp $ g . f

instance ContraApp (Opp a) where
  pureDisunit = const ()
  fcontraunzip z (Opp g)
     = (Opp $ \a -> ???, Opp $ \b -> ???) -- `z` needs both `a` and `b`, can't get it!

I don't think this is useful, though you might be able to define it with something like clever knot-tying recursion.

What might be more interesting is a contravariant co-monoidal functor, but this gets too weird for me right now.



来源:https://stackoverflow.com/questions/30641500/are-there-contravariant-monads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!