-- |
-- Module : Data.Monoid
-- Copyright : (c) Andy Gill 2001,
--- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
--- Portability : non-portable (requires extended type classes)
+-- Portability : portable
--
--- Declaration of the Monoid class, and instances for list and functions.
+-- The Monoid class with various general-purpose instances.
--
-- Inspired by the paper
-- /Functional Programming with Overloading and
-----------------------------------------------------------------------------
module Data.Monoid (
- Monoid(..)
+ Monoid(..),
+ Dual(..),
+ Endo(..),
+ All(..),
+ Any(..),
+ Sum(..),
+ Product(..)
) where
import Prelude
mempty = []
mappend = (++)
-instance Monoid (a -> a) where
- mempty = id
- mappend = (.)
+instance Monoid b => Monoid (a -> b) where
+ mempty _ = mempty
+ mappend f g x = f x `mappend` g x
instance Monoid () where
-- Should it be strict?
LT `mappend` _ = LT
EQ `mappend` y = y
GT `mappend` _ = GT
+
+-- | The dual of a monoid, obtained by swapping the arguments of 'mappend'.
+newtype Dual a = Dual { getDual :: a }
+
+instance Monoid a => Monoid (Dual a) where
+ mempty = Dual mempty
+ Dual x `mappend` Dual y = Dual (y `mappend` x)
+
+-- | The monoid of endomorphisms under composition.
+newtype Endo a = Endo { appEndo :: a -> a }
+
+instance Monoid (Endo a) where
+ mempty = Endo id
+ Endo f `mappend` Endo g = Endo (f . g)
+
+-- | Boolean monoid under conjunction.
+newtype All = All { getAll :: Bool }
+ deriving (Eq, Ord, Read, Show, Bounded)
+
+instance Monoid All where
+ mempty = All True
+ All x `mappend` All y = All (x && y)
+
+-- | Boolean monoid under disjunction.
+newtype Any = Any { getAny :: Bool }
+ deriving (Eq, Ord, Read, Show, Bounded)
+
+instance Monoid Any where
+ mempty = Any False
+ Any x `mappend` Any y = Any (x || y)
+
+-- | Monoid under addition.
+newtype Sum a = Sum { getSum :: a }
+ deriving (Eq, Ord, Read, Show, Bounded)
+
+instance Num a => Monoid (Sum a) where
+ mempty = Sum 0
+ Sum x `mappend` Sum y = Sum (x + y)
+
+-- | Monoid under multiplication.
+newtype Product a = Product { getProduct :: a }
+ deriving (Eq, Ord, Read, Show, Bounded)
+
+instance Num a => Monoid (Product a) where
+ mempty = Product 1
+ Product x `mappend` Product y = Product (x * y)