
<p>In <a href="https://stackoverflow.com/a/23316850/1333025">this post on SO</a> I found an interesting answer - <a href="https://fplab.bitbucket.io/posts/2007-07-08-decisive-functors.html" rel="nofollow noreferrer">decisive functors</a>. If we replace <code>()</code> by <code>Void</code>, <code>(,)</code> by <code>Either</code> <em>and</em> reverse the arrows, we get:</p>
<pre><code>class Functor f =&gt; Decisive f where
    nogood :: f Void -&gt; Void
    orwell :: f (Either s t) -&gt; Either (f s) (f t)
</code></pre>
<p>The blog post also gives some laws that decisive functors adhere to.</p>
<p>And, every <code>Comonad</code> is also <code>Decisive</code>:</p>
<pre><code>nogoodW :: (Comonad f) =&gt; f Void -&gt; Void
nogoodW = counit

orwellW :: (Comonad f) =&gt; f (Either s t) -&gt; Either (f s) (f t)
orwellW story = case counit story of
                      Left s  -&gt; fmap (either id (const s)) story
                      Right t -&gt; fmap (either (const t) id) story 
</code></pre>
<p>So decisive functors fit in between functors and comonads, just as applicative functors fit in between functors and monads.</p>

CC BY-SA 4.0
2014-04-27T07:22:31.747Z
2023-08-28T14:21:18.100Z
2023-08-28T14:21:18.100Z
Petr
<p><a href="http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf" rel="nofollow">McBride and Patterson</a> (Section 7) show that an applicative functor, also known as an idiom, is a <em>strong lax monoidal functor</em>. You are looking for a <em>strong colax monoidal functor</em> also known as an <em>strong oplax monoidal functor</em>.  As mentioned in a comment, an oplax monoidal functor is a lax monoidal functor between the opposite categories, which ends up being a comonoidal version of a lax monoidal functor. </p>

<p>Draw the diagrams, reverse the arrows!</p>

<p>I'd have to spend a bit of time working out the details to see which it is, and to translate it into a functional programming notion.</p>

CC BY-SA 3.0
2013-01-28T20:13:02.107Z
For some reason the standard term seems to be "oplax monoidal functor". The idea is a lax monoidal functor between the opposite categories, which ends up being a comonoidal version of a lax monoidal functor. Using "colax comonoidal" is either redundant or equivalent to "lax monoidal".
C. A. McCann
CC BY-SA 3.0
2013-01-28T21:08:54.940Z
I overdid the "co"-ing. I'll fix my answer.
Dave Clarke
CC BY-SA 3.0
2013-01-27T12:23:43.760Z
2014-04-27T10:12:18.897Z
2014-04-27T10:12:18.897Z
Dave Clarke
<p>First of all:</p>

<blockquote>
  <p>Any monad is also an applicative functor and any applicative functor is a functor.</p>
</blockquote>

<p>This is true in the context of Haskell, but (reading <code>Applicative</code> as "strong lax monoidal functor") not in general, for the rather trivial reason that you can have "applicative" functors between different monoidal categories, whereas monads (and comonads) are endofunctors.</p>

<p>Further, identifying <code>Applicative</code> with strong lax monoidal functors is slightly misleading, because to justify the name (and the type signature of <code>(&lt;*&gt;)</code>) requires a functor between <a href="http://ncatlab.org/nlab/show/closed+monoidal+category">closed monoidal categories</a> which preserves both the <a href="http://ncatlab.org/nlab/show/monoidal+functor">monoidal structure</a> and the <a href="http://ncatlab.org/nlab/show/closed+functor">internal hom</a>. This could plausibly be called a "lax closed monoidal functor", except that a functor between monoidal closed categories that preserves either property preserves the other in <a href="http://ncatlab.org/nlab/show/currying">the obvious way</a>. Because <code>Applicative</code> describes only endofunctors on <strong>Hask</strong> preserving the monoidal structure of <code>(,)</code>, its instances gain a lot of properties automatically, including their <a href="http://ncatlab.org/nlab/show/tensorial+strength">strength</a>, which can thus be elided.</p>

<p>The apparent connection with <code>Monad</code> is arguably an artifact of the implicit limitations on <code>Applicative</code> causing aspects of their respective monoid structures to coincide, a happy coincidence which unfortunately does not survive dualization.</p>

<p>Just as a comonad on a category $C$ is a monad on $C^{op}$, an <a href="http://ncatlab.org/nlab/show/oplax+monoidal+functor">oplax monoidal functor</a> $C \rightarrow D$ is a lax monoidal functor $C^{op} \rightarrow D^{op}$. But $ \boldsymbol{Hask}^{op}$ is not monoidal <em>closed</em>, and a co-<code>Applicative</code> that doesn't include function application hardly merits the name. Anyway, the result wouldn't be terribly interesting:</p>

<pre><code>class (Functor f) =&gt; CoMonoidal f where
    counit :: f () -&gt; ()
    cozip :: f (a, b) -&gt; (f a, f b)
</code></pre>

<p>We could instead imagine a notion of "colax closed functor", which would look much more like <code>Applicative</code> if it existed. Unfortunately, $\boldsymbol{Hask}^{op}$ is not (to the best of my knowledge) a closed category at all: <code>newtype Op b a = Op (a -&gt; b)</code> in $\boldsymbol{Hask}$ corresponds to morphisms $b \rightarrow a$ in $\boldsymbol{Hask}^{op}$, but <code>Op b a</code> doesn't work as an internal hom there--because the arrows are reversed some sort of co-function would be required instead, which we can't define in general for $\boldsymbol{Hask}$.</p>

<p>If we simply pretend that "colax closed functors" existed for $\boldsymbol{Hask}$, and furthermore worked in the way we'd naively hope they would, a co-<code>Applicative</code> based on that would probably look like this:</p>

<pre><code>class (Functor f) =&gt; CoApplicative f where
    copure :: f a -&gt; a
    coap :: (f a -&gt; f b) -&gt; f (a -&gt; b)
</code></pre>

<p>Adding <code>duplicate :: f a -&gt; f (f a)</code> to <code>copure</code> would produce a comonad (assuming the laws are satisfied), of course. But there's no obvious relationship between <code>coap</code>--whatever it might be--and <code>extend :: (f a -&gt; b) -&gt; f a -&gt; f b</code>. Comparing the types it becomes clear that the dualization is happening in different ways: the comonoidal structures underlying <code>duplicate</code> and <code>cozip</code> have little to do with each other or with <code>coap</code> (which probably doesn't make sense anyway), whereas <code>liftA2 (,)</code> and <code>(&lt;*&gt;)</code> are equivalent and can be derived from <code>join</code>.</p>

<p>Another possible way of dualizing <code>Applicative</code>, which has even less to do with comonads, is to consider contravariant monoidal functors:</p>

<pre><code>class (Contravariant f) =&gt; ContraMonoidal f where
    contraunit :: f a
    contrazip :: f a -&gt; f b -&gt; f (Either a b)
</code></pre>

<p>But this runs afoul of the same issues as above, namely that $\boldsymbol{Hask}^{op}$ is not a closed category. If it were, we would have some type <code>b &lt;~ a</code> such that we could write functions like <code>contracurry :: (Either c b &lt;~ a) -&gt; (c &lt;~ (b &lt;~ a))</code> and <code>contraapply :: b -&gt; Either a (a &lt;~ b)</code> and so on that actually worked as expected.</p>

<p>If memory serves me, the obstacles here are not specific to Haskell, but rather arise from $\boldsymbol{Hask}$ being <a href="http://ncatlab.org/nlab/show/cartesian+closed+category">cartesian closed</a> (up to the usual hand-waving, of course), a property it shares with most typed lambda calculi, so you're not likely to get very far with a <code>CoApplicative</code> in most settings. </p>

<p>However, in a monoidal closed category more hospitable to dualization you might have better luck. In particular, I believe both <code>Kleisli (Cont r)</code> and its opposite category are monoidal closed, so that might be a better context to explore these ideas.</p>

CC BY-SA 3.0
2017-02-21T17:30:08.040Z
Comparing your answer to http://cstheory.stackexchange.com/a/22302/989, it's surprising that you don't dualize products to sums. Of course, you're right that Hask doesn't have categorical sums; but if you're willing to restrict to the category of total programs (like in Agda), let's pretend it's Set for now, that problem disappears. (I'm not saying Set^op is monoidal closed, but I suspect what I'm saying implies it).
Blaisorblade
CC BY-SA 3.0
2013-01-28T20:01:40.100Z
2013-01-28T20:01:40.100Z
C. A. McCann
<p>Any monad is also an applicative functor and any applicative functor is a functor. Also, any comonad is a functor. Is there a similar concept between comonads and functors, something like co-applicative functor, and what are its properties?</p>

<p>\begin{array}{c}
\end{array}
\begin{array}{cc}
\mbox{Functors} &amp; &amp; \mbox{Functors} \\
\uparrow &amp; &amp; \uparrow \\
\mbox{Applicative functors} &amp; &amp; ??? \\
\uparrow &amp; &amp; \uparrow \\
\mbox{Monads} &amp; &amp; \mbox{Comonads} \\
\end{array}</p>

<p><em>Update:</em> I'd be also interested in possible uses of such a concept.</p>

CC BY-SA 3.0
2016-04-09T02:50:34.393Z
Are you sure you weren't looking for Comonads -> ??? -> Cofunctors?
josiah
CC BY-SA 3.0
2016-04-09T11:14:17.980Z
@josiah No, as far as I know, [comonads are functors](https://hackage.haskell.org/package/comonad-5/docs/Control-Comonad.html#t:Comonad), not cofunctors.
Petr
CC BY-SA 4.0
2018-06-07T21:22:35.747Z
Isn't [divisible](http://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant-Divisible.html) that missing piece?
Gus
CC BY-SA 4.0
2021-03-27T09:50:37.613Z
@Petr Yes, comonads are functors, but [cofunctors are functors](https://stackoverflow.com/questions/34732571/why-there-is-no-cofunctor-typeclass-in-haskell).
NJay
<ct.category-theory><monad><applicative><comonad>
Is there a concept of something like co-applicative functors sitting between comonads and functors?
Petr
# Is there a concept of something like co-applicative functors sitting between comonads and functors?

(Asked by: username_0 on 2013-01-27)

Any monad is also an applicative functor and any applicative functor is a functor. Also, any comonad is a functor. Is there a similar concept between comonads and functors, something like co-applicative functor, and what are its properties?

\begin{array}{c}
\end{array}
\begin{array}{cc}
\mbox{Functors} & & \mbox{Functors} \\
\uparrow & & \uparrow \\
\mbox{Applicative functors} & & ??? \\
\uparrow & & \uparrow \\
\mbox{Monads} & & \mbox{Comonads} \\
\end{array}

*Update:* I'd be also interested in possible uses of such a concept.

**Tags:** ct.category-theory, monad, applicative, comonad
> **Comments:**
> **username_1**: Are you sure you weren't looking for Comonads -> ??? -> Cofunctors?  
> **username_0**: @josiah No, as far as I know, [comonads are functors](https://hackage.haskell.org/package/comonad-5/docs/Control-Comonad.html#t:Comonad), not cofunctors.  
> **username_2**: Isn't [divisible](http://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant-Divisible.html) that missing piece?  
> **username_3**: @Petr Yes, comonads are functors, but [cofunctors are functors](https://stackoverflow.com/questions/34732571/why-there-is-no-cofunctor-typeclass-in-haskell).  

---

## 3 answers

### Answer by username_5 on 2013-01-28. Score: 21 | Accepted answer

First of all:

Any monad is also an applicative functor and any applicative functor is a functor.

This is true in the context of Haskell, but (reading Applicative as "strong lax monoidal functor") not in general, for the rather trivial reason that you can have "applicative" functors between different monoidal categories, whereas monads (and comonads) are endofunctors.
Further, identifying Applicative with strong lax monoidal functors is slightly misleading, because to justify the name (and the type signature of (<*>)) requires a functor between closed monoidal categories which preserves both the monoidal structure and the internal hom. This could plausibly be called a "lax closed monoidal functor", except that a functor between monoidal closed categories that preserves either property preserves the other in the obvious way. Because Applicative describes only endofunctors on Hask preserving the monoidal structure of (,), its instances gain a lot of properties automatically, including their strength, which can thus be elided.
The apparent connection with Monad is arguably an artifact of the implicit limitations on Applicative causing aspects of their respective monoid structures to coincide, a happy coincidence which unfortunately does not survive dualization.
Just as a comonad on a category $C$ is a monad on $C^{op}$, an oplax monoidal functor $C \rightarrow D$ is a lax monoidal functor $C^{op} \rightarrow D^{op}$. But $ \boldsymbol{Hask}^{op}$ is not monoidal closed, and a co-Applicative that doesn't include function application hardly merits the name. Anyway, the result wouldn't be terribly interesting:
class (Functor f) => CoMonoidal f where
    counit :: f () -> ()
    cozip :: f (a, b) -> (f a, f b)

We could instead imagine a notion of "colax closed functor", which would look much more like Applicative if it existed. Unfortunately, $\boldsymbol{Hask}^{op}$ is not (to the best of my knowledge) a closed category at all: newtype Op b a = Op (a -> b) in $\boldsymbol{Hask}$ corresponds to morphisms $b \rightarrow a$ in $\boldsymbol{Hask}^{op}$, but Op b a doesn't work as an internal hom there--because the arrows are reversed some sort of co-function would be required instead, which we can't define in general for $\boldsymbol{Hask}$.
If we simply pretend that "colax closed functors" existed for $\boldsymbol{Hask}$, and furthermore worked in the way we'd naively hope they would, a co-Applicative based on that would probably look like this:
class (Functor f) => CoApplicative f where
    copure :: f a -> a
    coap :: (f a -> f b) -> f (a -> b)

Adding duplicate :: f a -> f (f a) to copure would produce a comonad (assuming the laws are satisfied), of course. But there's no obvious relationship between coap--whatever it might be--and extend :: (f a -> b) -> f a -> f b. Comparing the types it becomes clear that the dualization is happening in different ways: the comonoidal structures underlying duplicate and cozip have little to do with each other or with coap (which probably doesn't make sense anyway), whereas liftA2 (,) and (<*>) are equivalent and can be derived from join.
Another possible way of dualizing Applicative, which has even less to do with comonads, is to consider contravariant monoidal functors:
class (Contravariant f) => ContraMonoidal f where
    contraunit :: f a
    contrazip :: f a -> f b -> f (Either a b)

But this runs afoul of the same issues as above, namely that $\boldsymbol{Hask}^{op}$ is not a closed category. If it were, we would have some type b <~ a such that we could write functions like contracurry :: (Either c b <~ a) -> (c <~ (b <~ a)) and contraapply :: b -> Either a (a <~ b) and so on that actually worked as expected.
If memory serves me, the obstacles here are not specific to Haskell, but rather arise from $\boldsymbol{Hask}$ being cartesian closed (up to the usual hand-waving, of course), a property it shares with most typed lambda calculi, so you're not likely to get very far with a CoApplicative in most settings. 
However, in a monoidal closed category more hospitable to dualization you might have better luck. In particular, I believe both Kleisli (Cont r) and its opposite category are monoidal closed, so that might be a better context to explore these ideas.

> **Comments:**
> **username_6**: Comparing your answer to http://cstheory.stackexchange.com/a/22302/989, it's surprising that you don't dualize products to sums. Of course, you're right that Hask doesn't have categorical sums; but if you're willing to restrict to the category of total programs (like in Agda), let's pretend it's Set for now, that problem disappears. (I'm not saying Set^op is monoidal closed, but I suspect what I'm saying implies it).  

---

### Answer by username_0 on 2014-04-27. Score: 11

In this post on SO I found an interesting answer - decisive functors. If we replace () by Void, (,) by Either and reverse the arrows, we get:
class Functor f => Decisive f where
    nogood :: f Void -> Void
    orwell :: f (Either s t) -> Either (f s) (f t)

The blog post also gives some laws that decisive functors adhere to.
And, every Comonad is also Decisive:
nogoodW :: (Comonad f) => f Void -> Void
nogoodW = counit

orwellW :: (Comonad f) => f (Either s t) -> Either (f s) (f t)
orwellW story = case counit story of
                      Left s  -> fmap (either id (const s)) story
                      Right t -> fmap (either (const t) id) story 

So decisive functors fit in between functors and comonads, just as applicative functors fit in between functors and monads.


---

### Answer by username_4 on 2013-01-27. Score: 6

[McBride and Patterson](http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf) (Section 7) show that an applicative functor, also known as an idiom, is a *strong lax monoidal functor*. You are looking for a *strong colax monoidal functor* also known as an *strong oplax monoidal functor*. As mentioned in a comment, an oplax monoidal functor is a lax monoidal functor between the opposite categories, which ends up being a comonoidal version of a lax monoidal functor.

Draw the diagrams, reverse the arrows!

I'd have to spend a bit of time working out the details to see which it is, and to translate it into a functional programming notion.

> **Comments:**
> **username_5**: For some reason the standard term seems to be "oplax monoidal functor". The idea is a lax monoidal functor between the opposite categories, which ends up being a comonoidal version of a lax monoidal functor. Using "colax comonoidal" is either redundant or equivalent to "lax monoidal".  
> **username_4**: I overdid the "co"-ing. I'll fix my answer.  

---

