Functorの混乱

[追記:おかしいところについて]用語の混乱があったり、勉強不足があったりで、間違ったことを書いてあります。まず、functorなんですが、これは圏論での関手が英語圏ではfunctorと呼ばれていたり、C++などで使われるファンクターというものがあったり、さらに、_さんがコメントで指摘してくれたように、HaskellではFunctorというクラスがあります。この辺がごちゃ混ぜになってしまっています。
まず、半群(semi group), モノイド, 群(group),は全てHaskellで言うところのFunctorとも圏論の関手とも関係はなく、むしろ、f:: (G a) => a->a->aという関数の部分集合に当たるようです。HaskellのMonoidとここで説明したモノイドはどうやら同じもののようです。

以前に読んだApplicativeの論文では、ApplicativeパターンのことをApplicative functorと呼び、"Monoids are phantom Applicative functors"というセクションもあります。今はちょっと時間が取れなくて、それがどうゆう意味なのか理解するところまで行っていないのですが…
ただ、Monoidはその定義の中に2項演算があるのに対して、Haskellで言うところのFunctorは何かの形でデータを保有している型に単項演算を適用するパターンを記述しているわけですよね...そういった意味で、根本的にコンパチビリティーがない関係のようにも見えてきます。

FunctorとMonadの間には親子クラス関係とも言っていいような関係があるようです。(http://itpro.nikkeibp.co.jp/article/COLUMN/20061005/249933/?P=2&ST=ittrend
FunctorとArrowもかなり強い関係性があるようですが、それが親子クラスとして定義できるほどなのかは今の僕には良くわかりません…
とりあえず、半群、モノイド、群に関する記述はそんなに間違っているようではないようです...僕のようにHaskellを勉強している人が読んだら、更なる混乱を招くだけな酔うなきもするので、このエントリー、削除しちゃおうかとも思ったのですが、もうちょっとさらしておいてから、考えようと思います。 ということで、僕のFunctorの混乱はいまだに続いているようです。



<ここはおかしい>質問です。MonadもMonoidもArrowもFunctorのサブクラスであるというのをどこかで読んだわけです。

Functor(関手)とはつまりa->bなもの全てなわけですよね…</ここはおかしい>
だとしたら、なぜMonoidやMonadインスタンスにリストがあるのでしょう?リストはともかく、OrderingまでMonoidのインスタンスになっています…

これがわからないまま、ずーっときていたのですが、Wikipediaに少し解説があるのを発見しました…

とりあえず、理解できたところまでで、登場してくるものは、半群・群・モノイドです。

半群とは「結合則を満たす2項演算の定義された集合」

だそうで、半群というのは特定の種類の集合の性質を表しているわけですね…ただし、ここでもう一つ指定されているのは、「結合側を満たす2項演算」がその集合に対して存在するということですね…この条件を満たす演算を
f :: (G a) => a -> a -> a
とすると、
f (f a b) c = f(a f(b c))
となる関数fと集合Gの2つがあって初めて「集合Gは関数fに関して半群である」といえるということです…

モノイドは「集合Gが関数fに関して半群であり、さらに単位元をもつもの」

ここで言う単位元とは集合Gの任意の要素にa対してf a e == f e a == aとなるような特殊な元(要素)eのことです。整数集合の足し算における単位元は0、掛け算における単位元は1ですね...

群は「集合Gが関数fに関してモノイドでさらに単位元、逆元を持つもの」

逆元とは、集合Gの任意の要素aに対してf a x == f x a == eとなるような元xのことらしいです。単位元は全ての要素に対して同じ元が単位元としての効果を持ちますが、逆元は、ある特定の元がその集合の全て元に対する逆元である必要はないようです。整数における足し算では任意の整数aの逆元は(-a)ということになりますね…

つまり、群はモノイドのサブクラスであり、モノイドは半群の部分集合である...そして、ここまでの理解をもってHaskellのMonoidクラスの定義を見ると:

class Monoid a where
	mempty :: a
	mappend :: a -> a -> a
	mconcat :: [a] -> a 

ということで、どうやらmemptyが単位元のことを意味しているようだということがわかります。mappendは型aがモノイドになりうる結合則を満たす演算のことなわけでしょう。mconcatはmappendを利用してリストをfoldするのが便利だということでMonoidクラスの定義に入り込んだということでしょうか…

つまりモノイドのインスタンス定義をするということは、モノイドのインスタンスになる型と、その型において結合側を満たす関数、そして、その関数における単位元を指定するということになるので、確かにWikipediaに書かれていた数学側でのMonoidに必要な条件を全て指定することになります...なるほど…

ちなみに、Numな型に対しては、ProductとSumという型がMonoidになっています。これはつまり、整数などは足し算と掛け算の両方に関してモノイドなので、ProductやSumという補助型でどちらの関数の話をしているかというのを限定しているということみたいですね…

<ここはおかしい>今まで、気軽に、リストはモナドだからとかモノイドだからとか言ってましたが、言うたびになんだか混乱したような気分になっていた理由がわかりました…
モノイドの定義に関して言えば、リストなどの型もインスタンスの定義内で指定されていますが、mappendとしてモノイドにかかわるFunctorを指定しているので、Functorのサブクラスというのは、ここまでわかってから見れば、確かにそうかなぁと言う感じですね...
</ここはおかしい>

さて、モノイドなんかよりよっぽど良く使うモナドのほうなんですが、はっきり言ってもっと大分難しいです。また今度わかったときに書けたらいいなと思います。

ではでは。