{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, GeneralizedNewtypeDeriving, FlexibleContexts #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Monoid.Applicative -- Copyright : (c) Edward Kmett 2009 -- License : BSD-style -- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : non-portable (MPTCs) -- -- 'Monoid' instances for working with a 'Monad' -- ----------------------------------------------------------------------------- module Data.Monoid.Monad ( module Data.Monoid.Reducer , module Data.Ring.Semi.Near -- * Actions , Action(Action,getAction) , snocAction -- * Wrapped Monads , WrappedMonad(WrappedMonad, getWrappedMonad) ) where import Control.Functor.Pointed import Data.Monoid.Reducer import Data.Ring.Semi.Near import Control.Monad -- | An 'Action' uses glues together 'Monad' actions with (>>) -- in the manner of 'mapM_' from "Data.Foldable". Any values returned by -- reduced actions are discarded. newtype Action m = Action { getAction :: m () } instance Monad m => Monoid (Action m) where mempty = Action (return ()) Action a `mappend` Action b = Action (a >> b) instance Monad m => Reducer (m a) (Action m) where unit a = Action (a >> return ()) a `cons` Action b = Action (a >> b) Action a `snoc` b = Action (a >> b >> return ()) {-# RULES "unitAction" unit = Action #-} {-# RULES "snocAction" snoc = snocAction #-} -- | Efficiently avoid needlessly rebinding when using 'snoc' on an action that already returns () -- A rewrite rule automatically applies this when possible snocAction :: Reducer (m ()) (Action m) => Action m -> m () -> Action m snocAction a = mappend a . Action -- | A 'WrappedMonad' turns any 'MonadPlus' instance into a 'Monoid'. -- It also provides a 'Multiplicative' instance for a 'Monad' wrapped around a 'Monoid' -- and asserts that any 'MonadPlus' applied to a 'Monoid' forms a 'LeftSemiNearRing' -- under these operations. newtype WrappedMonad m a = WrappedMonad { getWrappedMonad :: m a } deriving (Eq,Ord,Show,Read,Functor,Pointed, Monad,MonadPlus) instance (Monad m, Monoid a) => Multiplicative (WrappedMonad m a) where one = WrappedMonad (return mempty) WrappedMonad m `times` WrappedMonad n = WrappedMonad (liftM2 mappend m n) instance (MonadPlus m) => Monoid (WrappedMonad m a) where mempty = mzero mappend = mplus instance (MonadPlus m, c `Reducer` a) => Reducer c (WrappedMonad m a) where unit = WrappedMonad . return . unit instance (MonadPlus m, Monoid a) => LeftSemiNearRing (WrappedMonad m a)