ウルフラムから:
モノイドは、連想二項演算で閉じられた集合であり、S 内のすべての a に対して Ia=aI=a となる恒等元 I を S 内に持ちます。
ウィキから:
数学の一分野である抽象代数では、モノイドは単一の連想二項演算と単位要素を持つ代数構造です。
したがって、あなたの直感は多かれ少なかれ正しいです。
Haskell の「カスタム セット」ではなく、タイプに対して定義されていることに注意してください。違いはわずかですが (型理論の型は集合論の集合と非常に似ているため)、Monoid インスタンスを定義できる型は、数学的な集合を表す型である必要はありません。
つまり、タイプは、そのタイプのすべての値のセットを記述します。モノイドは「インターフェース」であり、そのインターフェースに準拠すると主張する型は、その型の 2 つの値を結合する 2 項演算である ID 値を提供する必要があり、すべての一般的なモノイド演算が意図したとおりに機能し (モノイド値のリストの一般的な合計など)、非論理的/矛盾した結果を生成しません。
また、型が Monoid クラスのインスタンスであるためには、そのセット (型) に ID 要素が存在する必要があることに注意してください。
たとえば、自然数は両方の加算 (identity = 0
)の下でモノイドを形成します。
0 + n = n
n + 0 = n
乗算と同様に (identity = 1
):
1 * n = n
n * 1 = n
++
また、リストは(identity = []
)の下でモノイドを形成します。
[] ++ xs = xs
xs ++ [] = xs
また、型の関数はa -> a
構成下でモノイドを形成します (identity = id
)
id . f = f
f . id = f
そのため、モノイドはセットを表す型ではなく、セットとして見たときの型に関するものであることに留意することが重要です。
不正に構築されたモノイド インスタンスの例として、次のことを考慮してください。
import Data.Monoid
newtype MyInt = MyInt Int deriving Show
instance Monoid MyInt where
mempty = MyInt 0
mappend (MyInt a) (MyInt b) = MyInt (a * b)
mconcat
ここで値のリストを取得しようとすると、ID 値と 2 項演算がうまく連携しないため、MyInt
常に結果が得られます。MyInt 0
0
*
λ> mconcat [MyInt 1, MyInt 2]
MyInt 0