Haskell Language
Monoid
Zoeken…
Een exemplaar van Monoid voor lijsten
instance Monoid [a] where
mempty = []
mappend = (++)
Controle van de Monoid
wetten voor deze instantie:
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
Een lijst met monoiden samenvouwen tot een enkele waarde
mconcat :: [a] -> a
is een andere methode van de Monoid
typeclass :
ghci> mconcat [Sum 1, Sum 2, Sum 3]
Sum {getSum = 6}
ghci> mconcat ["concat", "enate"]
"concatenate"
De standaarddefinitie is mconcat = foldr mappend mempty
.
Numerieke monoiden
Getallen zijn op twee manieren monoidaal: optellen met 0 als eenheid en vermenigvuldigen met 1 als eenheid. Beide zijn even geldig en nuttig in verschillende omstandigheden. Dus in plaats van een voorkeursinstantie voor getallen te kiezen, zijn er twee newtypes
, Sum
en Product
om ze te taggen voor de verschillende functionaliteit.
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)
Dit stelt de ontwikkelaar in staat om te kiezen welke functionaliteit moet worden gebruikt door de waarde in het juiste nieuwe type te newtype
.
Sum 3 <> Sum 5 == Sum 8
Product 3 <> Product 5 == Product 15
Een exemplaar van Monoid voor ()
()
is een Monoid
. Aangezien er slechts één waarde van type ()
, is er maar één ding dat mempty
en mappend
kunnen doen:
instance Monoid () where
mempty = ()
() `mappend` () = ()