Ross Paterson ross at
Thu Jan 27 11:54:05 CET 2011

On Wed, Jan 26, 2011 at 03:56:12PM -0500, Edward Kmett wrote:
> 1.) Data.Functor.Product admits a useful monad instance.

Yes (once the typos are fixed), and it's compatible with the Applicative
instance.  While we're at it, we might as well add the MonadPlus and
MonadFix instances:

instance (MonadPlus f, MonadPlus g) => MonadPlus (Product f g) where
    mzero = Pair mzero mzero
    Pair x1 y1 `mplus` Pair x2 y2 = Pair (x1 `mplus` x2) (y1 `mplus` y2)

instance (MonadFix f, MonadFix g) => MonadFix (Product f g) where
    mfix f = Pair (mfix (fstP . f)) (mfix (sndP . f))
        fstP (Pair a _) = a
        sndP (Pair _ b) = b

> 2.) The instance for Applicative for MaybeT doesn't really follow the other
> instances for Applicative in transformers.

David Menendez has explained that this is needed for compatibility
with the Monad instance.

> 3.) Data.Functor.Constant is rather redundant given the existence
> of the identical Const functor in Control.Applicative (which is a
> module that Data.Functor.Constant depends upon!) The main thing
> that would need to be fixed is the addition of Traversable and
> Foldable to Control.Applicative.Const, which shouldn't be all that
> controversial. I'll propose that more formally separately, as that
> does directly fall under the libraries processes.

Yes, that was an oversight, considering I wrote both instances.  I think
it's better not to abbreviate the name, so I'd suggest moving Constant
into Control.Applicative (re-exported by Data.Functor.Constant) and
deprecating Const.  (Or just hiding Const in Control.Applicative.)

> 4.) For completeness, I'm including this here, although I sent it in
> a separate email to Ross the other day. A large number of the monad
> transformers admit reasonable definitions for Foldable/Traversable.

These all look good, though let's write the ErrorT ones as

instance (Foldable f) => Foldable (ErrorT e f) where
    foldMap f (ErrorT a) = foldMap (either (const mempty) f) a

instance (Traversable f) => Traversable (ErrorT e f) where
    traverse f (ErrorT a) =
        ErrorT <$> traverse (either (pure . Left) (fmap Right . f)) a

so we don't have to wait for the Either instances to appear in base.

5.) While we're talking about transformers, do you have an opinion on
#4517: Add Data.Functor.Backwards to transformers
It's just a choice between designs using one functor or two.

More information about the Libraries mailing list