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
…