generated at
Monoid型クラス
モノイドを表す型クラス
単位元付きの二項演算がある
m -> m -> m なので、無限に連結ができる
ex. 1 + 2 + 3 + ..
モノイド則を満たす
Semigroup型クラスを継承する



定義
hs
class Semigroup a => Monoid a where mempty :: a
hs
class Monoid a where mempty :: m mappend :: m -> m -> m mappend = (<>) mconcat :: [m] -> m mconcat = foldr mappend mempty
mempty単位元の存在を表す
mappendは二項演算
mconcat は多くの場合、デフォルト実装で済む


Monoidはinstanceそれ自身が値になる点が、他の多くの型クラスと違った印象があるmrsekut
例えば、 Monoid m 制約を必要とするような関数の定義の型を見ると
hs
foldMap :: (Monoid m, Foldable t) => (a -> m) -> t a -> m
こんな感じになる
多くの型クラスの場合は、 m a のように、 *->* なものとして扱われるが、Monoidの場合は * として見られることになる
具体的に言うなら例えば
m だけで Maybe Int の意味を持つ
多くの場合は、 m では Maybe だが
これがどれだけ例外的なものなのかはよくわからんけどmrsekut



雑な具体例
m -> m -> m のパターンが肝なので
m==Int のときなら * とか + とか max()
一方で == などは Int -> Int -> Bool なので🙅‍♀️
m==String のときなら、文字列連結 ++ とか
m==Bool のときなら、論理演算である and or とか
List
((++), [])
Maybe
(<>, Nothing)
関数
(<>, \_ -> mempty)

具体例
* を考える
hs
newtype Product a = Product { getProduct :: a } deriving (Eq, Ord, Read, Show, Bounded) instance Num a => Monoid (Product a) where mempty = Product 1 Product x `mappend` Product y = Product (x * y)
mempy 1
x * 1 x になる
mappend *
リスト考える
hs
instance Monoid [a] where mempty = [] mappend = (++)
x ++ [] x になる
hs
[1,2,3] `mappend` [4,5,6] -- [1,2,3,4,5,6] [1,2,3] <> [4,5,6] -- [1,2,3,4,5,6] mconcat [[1],[2,3],[4,5,6]] -- [1,2,3,4,5,6]
Booleanを考える
(演算子, 単位元) の組を (||, False) とするか、 (&&, True) とするかの二通りが考えられる
前者を Any 、後者は All と名付ける
hs
newtype Any = Any { getAny :: Bool } deriving (Eq, Ord, Read, Show, Bounded) instance Monoid Any where mempty = Any False Any x `mappend` Any y = Any (x || y)
hs
newtype All = All { getAll :: Bool } deriving (Eq, Ord, Read, Show, Bounded) instance Monoid All where mempty = All True All x `mappend` All y = All (x && y)
Ordering
すごいH本 p.272
Maybe a を考える
Maybe型のモノイドの定義は複数考えられる
a がモノイドである場合
hs
instance Monoid a => Monoid (Maybe a) where mempty = Nothing Nothing `mappend` m = m m `mappend` Nothing = m Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
a がモノイドでない場合
すごいH本 p.276
参考
自分自身への関数 a -> a を考える
引数と返り値の型が異なる関数はモノイドにならない
hs
newtype Endo a = Endo { appEndo :: a -> a } instance Monoid (Endo a) where mempty = Endo id Endo f <> Endo g = Endo (f . g)
単位元が恒等関数 id 、演算子は関数合成 .
max/min関数のモノイド
IO
hs
m1 <> m2 = do x1 <- m1 x2 <- m2 return $ x1 <> x2





モノイドの畳み込み
Foldable型クラスについて
ref すごいH本 p.277


Writerモナドとの関係性


fp-ts ref
ts
interface Monoid<A> extends Semigroup<A> { readonly empty: A }



参考
様々なモノイドの紹介、詳しい
モノイドの紹介。モノイドの各特徴の利点など
FizzBuzzの簡潔なコードを読み解く際にモノイドの解説がある(後半)
関数モノイド( Monoid (a -> b) )を利用している
その中で3重のモノイドが使われている
monoidを的確に使った記事
hsのパフォーマンスの話