{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, TypeOperators #-}------------------------------------------------------------------------------- |-- Module : Data.Monoid.Multiplicative-- Copyright : (c) Edward Kmett 2009-- License : BSD-style-- Maintainer : ekmett@gmail.com-- Stability : experimental-- Portability : portable (but instances use MPTCs)---- When dealing with a 'Ring' or other structure, you often need a pair of -- 'Monoid' instances that are closely related. Making a @newtype@ for one-- is unsatisfying and yields an unnatural programming style. ---- A 'Multiplicative' is a 'Monoid' that is intended for use in a scenario-- that can be extended to have another 'Monoid' slot in for addition. This-- enables one to use common notation.---- Any 'Multiplicative' can be turned into a 'Monoid' using the 'Log' wrapper.---- Any 'Monoid' can be turned into a 'Multiplicative' using the 'Exp' wrapper.---- Instances are supplied for common Monads of Monoids, in a fashion -- which can be extended if the 'Monad' is a 'MonadPlus' to yield a 'RightSemiNearRing'---- Instances are also supplied for common Applicatives of Monoids, in a-- fashion which can be extended if the 'Applicative' is 'Alternative' to-- yield a 'RightSemiNearRing'-----------------------------------------------------------------------------moduleData.Monoid.Multiplicative(Multiplicative,one,times-- * Multiplicative to Monoid,Log(Log,getLog)-- * Monoid to Multiplicative,Exp(Exp,getExp))whereimportControl.ApplicativeimportControl.Monad(liftM2)importData.Monoid(Monoid,mappend,mempty,Dual(..))importData.GeneratorimportData.Monoid.SelfimportData.RatioimportData.FingerTreeimportData.Sequence(Seq)classMultiplicativemwhereone::mtimes::m->m->minstanceMultiplicativem=>Multiplicative(Dualm)whereone=DualoneDualx`times`Dualy=Dual(y`times`x)-- | Convert a 'Multiplicative' into a 'Monoid'. Mnemonic: @Log a + Log b = Log (a * b)@dataLogm=Log{getLog::m}instanceMultiplicativem=>Monoid(Logm)wheremempty=LogoneLoga`mappend`Logb=Log(a`times`b)-- | Convert a 'Monoid' into a 'Multiplicative'. Mnemonic: @Exp a * Exp b = Exp (a + b)@dataExpm=Exp{getExp::m}instanceMonoidm=>Multiplicative(Expm)whereone=ExpmemptyExpa`times`Expb=Exp(a`mappend`b)instanceMultiplicativem=>Multiplicative(Selfm)whereone=SelfoneSelfa`times`Selfb=Self(a`times`b)instanceMonoidm=>Multiplicative[m]whereone=returnmemptytimes=liftM2mappendinstanceMonoidm=>Multiplicative(Maybem)whereone=returnmemptytimes=liftM2mappendinstanceMonoidn=>Multiplicative(IOn)whereone=returnmemptytimes=liftM2mappend-- Applicative instancesinstanceMonoidn=>Multiplicative(ZipListn)whereone=purememptytimes=liftA2mappendinstanceMonoidm=>Multiplicative(Constma)whereone=pureundefinedtimes=liftA2undefined-- Numeric instancesinstanceMultiplicativeIntwhereone=1times=(*)instanceMultiplicativeIntegerwhereone=1times=(*)instanceIntegralm=>Multiplicative(Ratiom)whereone=1times=(*)instanceMonoidm=>Multiplicative(Seqm)whereone=returnmemptytimes=liftM2mappend-- not quite be a Monad in Haskellinstance(Measuredvm,Monoidm)=>Multiplicative(FingerTreevm)whereone=singletonmemptyxss`times`yss=getSelf$mapReduce(flipfmap'yss.mappend)xss