module Data.Monoid.Multiplicative
( Multiplicative
, one, times
, Log(Log, getLog)
, Exp(Exp, getExp)
) where
import Control.Applicative
import Control.Monad (liftM2)
import Data.Monoid (Monoid, mappend, mempty, Dual(..))
import Data.Generator
import Data.Monoid.Self
import Data.Ratio
import Data.FingerTree
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
class Multiplicative m where
one :: m
times :: m -> m -> m
instance Multiplicative m => Multiplicative (Dual m) where
one = Dual one
Dual x `times` Dual y = Dual (y `times` x)
data Log m = Log { getLog :: m }
instance Multiplicative m => Monoid (Log m) where
mempty = Log one
Log a `mappend` Log b = Log (a `times` b)
data Exp m = Exp { getExp :: m }
instance Monoid m => Multiplicative (Exp m) where
one = Exp mempty
Exp a `times` Exp b = Exp (a `mappend` b)
instance Multiplicative m => Multiplicative (Self m) where
one = Self one
Self a `times` Self b = Self (a `times` b)
instance Monoid m => Multiplicative [m] where
one = return mempty
times = liftM2 mappend
instance Monoid m => Multiplicative (Maybe m) where
one = return mempty
times = liftM2 mappend
instance Monoid n => Multiplicative (IO n) where
one = return mempty
times = liftM2 mappend
instance Monoid n => Multiplicative (ZipList n) where
one = pure mempty
times = liftA2 mappend
instance Monoid m => Multiplicative (Const m a) where
one = pure undefined
times = liftA2 undefined
instance Multiplicative Int where
one = 1
times = (*)
instance Multiplicative Integer where
one = 1
times = (*)
instance Integral m => Multiplicative (Ratio m) where
one = 1
times = (*)
instance Monoid m => Multiplicative (Seq m) where
one = return mempty
times = liftM2 mappend
instance (Measured v m, Monoid m) => Multiplicative (FingerTree v m) where
one = singleton mempty
xss `times` yss = getSelf $ mapReduce (flip fmap' yss . mappend) xss