FP in Scala chapter notes - Chapter 11: Monads
The original is licensed using the MIT license.
モナドのもう一つの圏論的な見方は Eilenberg-Moore 圏だ。モナドの EM 圏は、モナドの代数の圏だ。
例えば、List
モナドの代数は Scala の Monoid
だ。List
モナドの EM 圏は、モノイドを対象 (object) としモノイド準同型(10 章を参照)を射 (arrow) とする圏だ。
一般的に、モナドの EM 圏は以下のメソッドに見られる (source: Theory Lunch):
- モナド
F
のF
-代数 は、型A
と、a(unit(x)) == x
かつa(join(x)) == a(map(x)(a))
であるような関数a: F[A] => A
で与えられる。 F
-代数a: F[A] => A
からF
-代数b: F[B] => B
へのF
-代数の射は、b(map(x)(f)) == f(a(x))
であるような関数f: A => B
で与えられる。- モナド
F
の Eilenberg-Moore 圏は、F
-代数を対象 (object) としF
-代数同士の射を射 (arrow) とする。恒等射はまさにidentity
関数で、射の合成は普通の関数合成で与えられる。
Monoid[A]
がまさに List
-代数であることをこの定義から見ることができる:
def fold[A](implicit M: Monoid[A]): List[A] => A =
_.foldRight(M.zero)(M.op)
これは List
-代数で、なぜなら fold(List(x)) == x
だからだ(つまり、何かをリストの中に入れて、次にそのリストを畳み込んでも何も起きない)。また、fold(x.flatten) == fold(x.map(fold.apply))
だ(つまり、一連のリスト群を結合してその結合したリストを畳み込むのと、一連のリスト群をそれぞれ畳み込んでその結果のリストを畳み込むのは同じことだ)。
これは、”List
はモノイドのモナドである”ということだ。
Option
の EM 圏も容易に見つけることができる(Edward Kmett に感謝)。型 Option[A] => A
についてのあらゆる Option
-代数は、型 A
の値 a
により与えられ、_.getOrElse(a)
で実装される。つまり Option
の EM 圏は、普通の Scala
の_値_を対象 (object) とし、全ての o: Option[A]
について o.map(f).getOrElse(b) == f(o.getOrElse(a))
を満たす 値 a:A
から 値 b:B
への Scala の関数 f: A => B
を射 (arrow) とする。つまり、これらの関数は a
を与えられると b
を返す。
Reader[R,_]
モナドの EM 圏は、対象 (object) のそれぞれが値 r:R
によって与えられ、_.run(r)
で実装される。射は、結果型 A
から他の型 B
への Scala の関数だ。
Id
(恒等モナド)の EM 圏は、Scala の型の圏そのものだ。