
Oops -- I wasn't watching this thread. I like Jules's definition, though
I'd write it as follows.
-- Standard instance: monad applied to monoid
instance Monoid a => Monoid (IO a) where
mempty = return mempty
mappend = liftM2 mappend
You can replace "IO" with any monad at all, to make similar instances.
Here's the instance i use. It's in Control.Instances in the TypeCompose
library. See http://www.haskell.org/haskellwiki/TypeCompose.
-- Standard instance: applicative functor applied to monoid
instance Monoid a => Monoid (IO a) where
mempty = pure mempty
mappend = (*>)
On second thought, I don't really like (*>), since it's easy to accidentally
discard a useful value. (I dislike (>>) for the same reason.) Generalizing
the "monad applied to monoid" instance above:
-- Standard instance: applicative functor applied to monoid
instance Monoid a => Monoid (IO a) where
mempty = pure mempty
mappend = liftA2 mappend
That will be the definition in the next TypeCompose release.
All of these instances agree for a = (). The first & third are more
compelling to me than the second, since they make full use of the Monoid a
constraint.
Cheers, - Conal
On 5/16/07, Jules Bean
On Wed, May 16, 2007 at 09:28:31AM +0100, Jules Bean wrote:
Tomasz Zielonka wrote:
You mean using the (Monoid b) => Monoid (a -> b) instance ? I can see that IO () makes a perfect Monoid, but there doesn't seem to be a standard instance for that.
Indeed, all Monads are Monoids (that is, if m :: * -> * is a Monad,
Tomasz Zielonka wrote: then
m a :: * is a Monoid, for any fixed type a) by using >>.
Are you sure that (IO Int) is a monoid with mappend = (>>)? How do you define mempty, so it is an identity for mappend?
It would help if type a was a Monoid, then:
mempty = return mempty mappend mx my = do x <- mx y <- my return (x `mappend` y)
It's easier if a = ().
Oops, you're right. I spoke too fast.
It's only a monoid for (). Otherwise you can't hope to have a right identity.
Jules