[project @ 2005-10-25 09:29:16 by ross]
[ghc.git] / libraries / base / Data / Monoid.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module : Data.Monoid
4 -- Copyright : (c) Andy Gill 2001,
5 -- (c) Oregon Graduate Institute of Science and Technology, 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
7 --
8 -- Maintainer : libraries@haskell.org
9 -- Stability : experimental
10 -- Portability : portable
11 --
12 -- The Monoid class with various general-purpose instances.
13 --
14 -- Inspired by the paper
15 -- /Functional Programming with Overloading and
16 -- Higher-Order Polymorphism/,
17 -- Mark P Jones (<http://www.cse.ogi.edu/~mpj/>)
18 -- Advanced School of Functional Programming, 1995.
19 -----------------------------------------------------------------------------
20
21 module Data.Monoid (
22 Monoid(..),
23 Endo(..),
24 Dual(..),
25 Sum(..),
26 Product(..)
27 ) where
28
29 import Prelude
30
31 -- ---------------------------------------------------------------------------
32 -- | The monoid class.
33 -- A minimal complete definition must supply 'mempty' and 'mappend',
34 -- and these should satisfy the monoid laws.
35
36 class Monoid a where
37 mempty :: a
38 -- ^ Identity of 'mappend'
39 mappend :: a -> a -> a
40 -- ^ An associative operation
41 mconcat :: [a] -> a
42
43 -- ^ Fold a list using the monoid.
44 -- For most types, the default definition for 'mconcat' will be
45 -- used, but the function is included in the class definition so
46 -- that an optimized version can be provided for specific types.
47
48 mconcat = foldr mappend mempty
49
50 -- Monoid instances.
51
52 instance Monoid [a] where
53 mempty = []
54 mappend = (++)
55
56 instance Monoid b => Monoid (a -> b) where
57 mempty _ = mempty
58 mappend f g x = f x `mappend` g x
59
60 instance Monoid () where
61 -- Should it be strict?
62 mempty = ()
63 _ `mappend` _ = ()
64 mconcat _ = ()
65
66 instance (Monoid a, Monoid b) => Monoid (a,b) where
67 mempty = (mempty, mempty)
68 (a1,b1) `mappend` (a2,b2) =
69 (a1 `mappend` a2, b1 `mappend` b2)
70
71 instance (Monoid a, Monoid b, Monoid c) => Monoid (a,b,c) where
72 mempty = (mempty, mempty, mempty)
73 (a1,b1,c1) `mappend` (a2,b2,c2) =
74 (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2)
75
76 instance (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a,b,c,d) where
77 mempty = (mempty, mempty, mempty, mempty)
78 (a1,b1,c1,d1) `mappend` (a2,b2,c2,d2) =
79 (a1 `mappend` a2, b1 `mappend` b2,
80 c1 `mappend` c2, d1 `mappend` d2)
81
82 instance (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) =>
83 Monoid (a,b,c,d,e) where
84 mempty = (mempty, mempty, mempty, mempty, mempty)
85 (a1,b1,c1,d1,e1) `mappend` (a2,b2,c2,d2,e2) =
86 (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2,
87 d1 `mappend` d2, e1 `mappend` e2)
88
89 -- lexicographical ordering
90 instance Monoid Ordering where
91 mempty = EQ
92 LT `mappend` _ = LT
93 EQ `mappend` y = y
94 GT `mappend` _ = GT
95
96 -- | The monoid of endomorphisms under composition.
97 newtype Endo a = Endo { appEndo :: a -> a }
98
99 instance Monoid (Endo a) where
100 mempty = Endo id
101 Endo f `mappend` Endo g = Endo (f . g)
102
103 -- | The dual of a monoid, obtained by swapping the arguments of 'mappend'.
104 newtype Dual a = Dual { getDual :: a }
105
106 instance Monoid a => Monoid (Dual a) where
107 mempty = Dual mempty
108 Dual x `mappend` Dual y = Dual (y `mappend` x)
109
110 -- | Monoid under addition.
111 newtype Sum a = Sum { getSum :: a }
112
113 instance Num a => Monoid (Sum a) where
114 mempty = Sum 0
115 Sum x `mappend` Sum y = Sum (x + y)
116
117 -- | Monoid under multiplication.
118 newtype Product a = Product { getProduct :: a }
119
120 instance Num a => Monoid (Product a) where
121 mempty = Product 1
122 Product x `mappend` Product y = Product (x * y)