First, since Monoid
s are not unique, neither are Writer
Monad
s or Applicative
s. Consider
data M a = M Int a
then you can give it Applicative
and Monad
instances isomorphic to either of:
Writer (Sum Int)
Writer (Product Int)
Given a Monoid
instance for a type s
, another isomorphic pair with different Applicative
/Monad
instances is:
ReaderT s (Writer s)
State s
As for having one Applicative
instance extend to two different Monad
s, I cannot remember any example. However, back when I tried to convince myself completely about whether ZipList
really cannot be made a Monad
, I found the following pretty strong restriction that holds for any Monad
:
join (fmap (x -> fmap (y -> f x y) ys) xs) = f <$> xs <*> ys
That doesn't give join
for all values though: in the case of lists the restricted values are the ones where all elements have the same length, i.e. lists of lists with "rectangular" shape.
(For Reader
monads, where the "shape" of monadic values doesn't vary, these are in fact all the m (m x)
values, so those do have unique extension. EDIT: Come to think of it, Either
, Maybe
and Writer
also have only "rectangular" m (m x)
values, so their extension from Applicative
to Monad
is also unique.)
I wouldn't be surprised if an Applicative
with two Monad
s exists, though.
For Alternative
/MonadPlus
, I cannot recall any law for instances using the Left Distribution law instead of Left Catch, I see nothing preventing you from just swapping (<|>)
with flip (<|>)
. I don't know if there's a less trivial variation.
ADDENDUM: I suddenly remembered I had found an example of an Applicative
with two Monad
s. Namely, finite lists. There's the usual Monad []
instance, but you can then replace its join
by the following function (essentially making empty lists "infectious"):
ljoin xs
| any null xs = []
| otherwise = concat xs
(Alas, the lists need to be finite because otherwise the null
check will never finish, and that would ruin the join . fmap return == id
monad law.)
This has the same value as join
/concat
on rectangular lists of lists, so will give the same Applicative
. As I recall, it turns out that the first two monad laws are automatic from that, and you just need to check ljoin . ljoin == ljoin . fmap ljoin
.