Semigroup and Monoid

Monoids enable parallel and incremental computation: because <> is associative, you can split work into chunks, combine partial results in any grouping, and get the same answer.

class Semigroup a where
  (<>) :: a -> a -> a                 -- associative: (a <> b) <> c == a <> (b <> c)

class Semigroup a => Monoid a where
  mempty :: a                         -- identity: mempty <> a == a == a <> mempty

-- Instances
[1, 2] <> [3]                          -- [1,2,3]
"ab" <> "cd"                           -- "abcd"
mconcat ["a", "b", "c"]                -- "abc"

import Data.Monoid
getSum (Sum 3 <> Sum 4)                -- 7
getProduct (foldMap Product [1 .. 5])  -- 120
getAll (foldMap (All . even) [2, 4])   -- True
getAny (foldMap (Any . odd) [2, 3])    -- True
getFirst (First (Just 1) <> First Nothing <> First (Just 3))   -- Just 1
Just [1] <> Nothing <> Just [2]        -- Just [1,2]
(compare 1 2) <> (compare 3 3)         -- LT: Ordering is a Monoid (lexicographic)

import Data.Semigroup (Max (..), Min (..))
sconcat (Max <$> 5 :| [3, 9])          -- Max 9 (sconcat needs only a Semigroup, on a NonEmpty)

-- Sorting by multiple keys with the Ordering monoid
import Data.Ord (comparing)
data Emp = Emp {dept :: String, salary :: Int} deriving Show
sortEmps :: [Emp] -> [Emp]
sortEmps = sortBy (comparing dept <> flip (comparing salary))   -- functions into a Mon
…