# Monoid

# An instance of Monoid for lists

instance Monoid [a] where
    mempty  = []
    mappend = (++)

Checking the Monoid laws for this instance:

mempty `mappend` x = x   <->   [] ++ xs = xs  -- prepending an empty list is a no-op

x `mappend` mempty = x   <->   xs ++ [] = xs  -- appending an empty list is a no-op

x `mappend` (y `mappend` z) = (x `mappend` y) `mappend` z
    <->
xs ++ (ys ++ zs) = (xs ++ ys) ++ zs           -- appending lists is associative

# Collapsing a list of Monoids into a single value

mconcat :: [a] -> a is another method of the Monoid typeclass (opens new window):

ghci> mconcat [Sum 1, Sum 2, Sum 3]
Sum {getSum = 6}
ghci> mconcat ["concat", "enate"]
"concatenate"

Its default definition is mconcat = foldr mappend mempty.

# Numeric Monoids

Numbers are monoidal in two ways: addition with 0 as the unit, and multiplication with 1 as the unit. Both are equally valid and useful in different circumstances. So rather than choose a preferred instance for numbers, there are two newtypes, Sum and Product to tag them for the different functionality.

newtype Sum n = Sum { getSum :: n }

instance Num n => Monoid (Sum n) where
    mempty = Sum 0
    Sum x `mappend` Sum y = Sum (x + y)

newtype Product n = Product { getProduct :: n }

instance Num n => Monoid (Product n) where
    mempty = Product 1
    Product x `mappend` Product y = Product (x * y)

This effectively allows for the developer to choose which functionality to use by wrapping the value in the appropriate newtype.

Sum 3     <> Sum 5     == Sum 8
Product 3 <> Product 5 == Product 15

# An instance of Monoid for ()

() is a Monoid. Since there is only one value of type (), there's only one thing mempty and mappend could do:

instance Monoid () where
    mempty = ()
    () `mappend` () = ()