モノイド

モナドというのがやはりよく分からないので、グーグルであちこち覗いていたら、モナドが分かるためにはモノイドが分からないといけないらしいと言う事が分かった。モノイドはWikipediaでは次のように解説してあった。

モノイドとは次のような集合 S をいう。
S 上に二項演算 · が定義されていて(すなわち、写像 · :S×S → S が存在して)、 次の二つの条件を満たす。

  1. (結合法則) 任意の a, b, c に対して (a · b ) · c = a · (b · c )
  2. (単位元の存在) ある e が存在して任意の a に対して e · a = a · e = a

ただし、a · b は · (a, b) を表す。

二項演算 · が条件の 1. を満たすとき、S は半群と呼ばれる。つまり、モノイドとは「半群であって単位元を持つもの」である。
また、二項演算 · が上のほかに、逆元の存在を満たすとき、S は群と呼ばれる。

これだけでは分かりにくいが、たとえば0を含む自然数の集合が加算という2項演算についてモノイドなのだそうだ。[0, 1, 2, ... ] という集合から適当に二つの数を取り出して足し合わせるとその答えはやはりこの集合の要素になる。例えば2と3を取り出して2+3をつくるとそれは5でやはりこの集合の要素になる。しかし、2と3をとりだしてタプル (2, 3) をつくってもこのタプルは自然数の集合の要素ではない。

さらに、(1+2)+3 = 6 で、1+(2+3) = 6 なので計算の順序を変えても同じ値になる。また、0はどの数に右から足してもひだりから足しても元の数と同じになる。つまり、0 + a = a + 0 = a となる。

したがって、集合 [0, 1, 2, .. ] がモノイドになるためには、演算 + の性質が大切なようだ。

ところで、Wikipedia の定義で (a · b ) · c = a · (b · c ) の a, b, c には自然数、ドットには加算を当てることができたが、これを抽象化して、a, b, c に関数、ドットに関数の合成をあてることもできそうだ。例えば、関数を f, g, h 関数の合成を . とおくと上の式は、(f . g) . h = f . (g . h) と表すことができる。これは、Haskell の >>= 演算子の使い方に似ている。つまり f , g が関数なら、f >>= g もまた、関数で、(f >>= g )>>= h と f >>= (g >>= h) は同じ結果をもたらす。モノイドと同じ構造を持ちながら、対象が関数で演算が関数の合成であるものがモナドだ。

つまり、モノイドが数の集合と(+)演算を対象にしていたのに対し、モナドは関数の集合と関数の合成を対象にしているのだ。言い換えると、モノイドの構造はモナドの構造と相同性があるのだ。モノイドで数値と(+)演算の関係として見ていたものを、モナドでは関数と関数を合成する演算子(>>=)の関係に置き換えて考えることができる。わかりにくいモナドの振る舞いを、もう少しわかりやすいモノイドというか0と正の自然数からなる集合と(+)演算の関係の類推で考えることができるということだ。
[PR]
by tnomura9 | 2009-08-27 05:57 | Haskell | Comments(0)
<< モナド 3の倍数と3のつく数 >>