generated at
Monoid
モノイド。掛け算っぽい演算ができる型のクラス
厳密に言うと、掛け算の重要な性質である結合法則 (a * b) * c = a * (b * c) を満たし、さらに a * 1 = 1 * a = a となる 1 のような値(単位元)を持つ型。単位元を持たない場合はSemigroup
haskell
class Semigroup a where (<>) :: a -> a -> a class Semigroup a => Monoid a where mempty :: a -- 非必須メンバは略

該当するものは非常に多く、たとえば整数や実数は足し算、掛け算どちらもモノイドとなるし、Boolは論理和も論理積もモノイドである。このため、 Int Bool は直接 Monoid にはなっておらず、newtypeでラップした Sum Any Monoid インスタンスを使用する事になる。

モノイドの便利な使い方
fold, foldMap
haskell
ghci> import Data.Foldable ghci> fold ["Long", "Cat", "Is", "Long"] "LongCatIsLong"
foldr (<>) mempty または foldl (<>) mempty と同じ意味なのだが、「要素ゼロ個の値がある」「foldrでもfoldlでも同じ値になる」ということが保障されるため文法的ノイズが非常に少なくなる。リストに限れば mconcat と同じ意味。
直接モノイドになっていない型でも foldMap を使えば行ける。
haskell
ghci> getAll $ foldMap All [True, False, False] False ghci> getAny $ foldMap Any [True, False, False] True

Writer
任意のモノイドはWriterを被せるとモナドになるので、do文で書ける。
haskell
print $ execWriter $ do tell "Long" tell "Cat" tell "Is" tell "Long"                           
リストで書いて mconcat でつなげるケースの方が多いか。
Writerはパフォーマンスの問題があるので、新しめのtransformersパッケージに入っているCPS版を使おう。Strictなら大丈夫、ではない。

主なモノイド
Sum
haskell
ghci> getSum $ foldMap Sum [1..5] 15

Product
haskell
ghci> getProduct $ foldMap Product [1..5] 120

Any
haskell
ghci> getAny $ foldMap Any [True, False, False] True

All
haskell
ghci> getAll $ foldMap All [True, False, False] False

大抵のはモノイドである。
haskell
mconcat [[1,2],[3],[4,5]] [1,2,3,4,5]
リストのように、結合にコストの掛かる構造だと、パフォーマンス問題が出る場合があるので注意。

文字列
大抵の文字列はモノイドである。
haskell
ghci> fold ["Long", "Cat", "Is", "Long"] "LongCatIsLong"
StringやTextのように結合にコストの掛かる構造だと(ry

Endo
Endomorphism。 a -> a の関数はモノイドである。
haskell
ghci> appEndo (foldMap Endo [abs,(*2),(+1),negate]) 2 2 -- abs ((*2) ((+1) (negate 2)))
どっちの順番で合成するのか分からなくなりがちだが、リストで書いたとき右にあるものを先に適用する順になるようだ。
これを使うと差分リストを使うためにdlistパッケージをインポートする必要がなくなる。
haskell
ghci> dlist = Endo ghci> dlistToList l = appEndo l [] ghci> dlistToList $ foldMap dlist [([1,2,3]++), ([4,5]++),([6]++)] [1,2,3,4,5,6]