Scalaで関数型プログラミングをする#3 圏論を学ぶ(前)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

※この記事はこれの再構成版です

Ⅰ.はじめに

圏論を知りましょう

さて、だいぶ前になってしまいましたが、前回の記事で、「関数型プログラミングを知るにはまず圏論から!」といいました。
※あくまでも私の考えです
私自身圏論についての知識がほぼないのですが、幸いにも圏論に関する初心者向け記事がWEB上にいっぱいあります。
その中でも、「Scalaで圏論入門」という記事は、初心者向けにわかりやすく記述されているので、
これを元に圏論について基本的な理解を深めていければと思います。
本記事は、この「Scalaで圏論入門」を読んだことがある人を対象にします。(理解できてもできなくても)一度読んでおいてください。

なんで圏論を知るべき?

なんで関数型プログラミングを知るのに圏論なんてわけわからんものを知らなければいけないのでしょうか。
この連載の目標(というか自分の目標)の1つとして、「scalazを使えるようにがんばる」という目標があります。
scalazに関する記事を見ると、「モナド」とか「関手」とかのキーワードが多く使用されています。
そのキーワード自体がよくわからないので、それを調べていくと「圏論」にいきつくわけです。
そのため、圏論の初歩的なものは学ぶ必要があるのではないかと思っています。

学ぶのは圏論の基礎の基礎です 初歩の初歩です(ご指摘により修正)

一般的(数学的?)な圏論は、定義が非常に広範囲かつ複雑な話になります。(たぶん)
そのため、当面の目標は、「scalazを解説しているドキュメントに書いてあるレベルのキーワードが理解できるようになる」
くらいの知識を目標として、「関数型プログラミングに関連する圏論をある程度知ろう」くらいのノリでいきます。

Ⅱ.用語を理解していこう

圏論って何だろう

そもそも「圏論」とはなんなのでしょうか。wikipediaには次のようにあります。

圏論(けんろん、category theory)とは、代数的な構成の変換の自然さを形式化するために導入された理論である。
射のクラスである圏とその間の対応である関手、構成の置き換えの自然さを表す自然変換が主な道具立てである。

これを見ただけで「ああ、そういうことね」と理解できる人はこの先を読む必要はありません。
私は最初これを読んだとき、「?」が10個くらい頭の上にでてきました。
どうやら圏論とは、「圏」というもモノに関する理論のようです。
また、次にあるように、あまり聞いたことがないキーワードがでてきました。

射のクラスである圏とその間の対応である関手、構成の置き換えの自然さを表す自然変換が主な道具立てである。

上の説明にある、「圏」や「射」や「関手」といったキーワードを1つずつ理解すれば、圏論とは何かがわかるはずです。
まずは「圏」とは何かを確認していきましょう。

圏とは何だろう

Scalaで圏論入門では、次のように書いてあります。

圏(category)とは、対象(object)と対象間のマップ(map)からなる。
マップは、射(morphism または arrow)とも言う。
マップは、結合則(associativity)にしたがって合成する(compose)ことができる。
また、それぞれの対象に対して、合成に関して中立な恒等射(identity map)が存在する。

またもや意味不明なキーワードが数多くでてきました。しかしここで挫けてはいけません。
重要なキーワードを1つずつ確認していきましょう。
なお、Scalaで圏論入門では、「犬、猫、象」と「草食、肉食」の、「2つの有限集合の圏」を例にして説明しています。
同じ例ではつまらないので、別の例を用意して確認していきましょう。
次のような例を使います。
ken01

人の名前と、職業が紐付いています。この例を元に、用語の説明をしていきましょう。

各用語の解説

圏(category)

圏とは、対象(object)とマップ(map、または射)というものから成り立つものです。
上記の図全体で圏となります。

対象(object)

図でいうと、「太郎、ジョン、花子が囲われた楕円」と「プログラマ、秘書が囲われた楕円」がそれぞれ対象と呼ばれるものになります。

ドメインとコドメイン

例の図では、ソース(source)からターゲット(target)への射(後述)を表しており、
これらは、「ドメイン」「コドメイン」とも呼ばれます。
例の図でいうと、「太郎、ジョン、花子が囲われた楕円」がドメイン、「プログラマ、秘書が囲われた楕円」がコドメインとなります。

マップ/射(map,arrow)

「対象 (object)」同士を接続するものが、「射」と呼ばれるものです。
例の図でいうと、「太郎からプログラマへ接続している矢印」や「花子から秘書へ接続している矢印」が「射」です。
なお、この図には矢印が3つありますが、この3つを全部合わせて1つの射です。
さらに、射が1つも存在しない圏、「離散圏」というものも存在することがあります。

プログラム的に書いてみる

では、例の図をプログラム的に表現してみましょう。
ドメイン(太郎、ジョン、花子のくくり)をPerson、コドメイン(プログラマ、秘書のくくり)をJobとします。
すると、射を次のように表現することができます。

func:Person -> Job

これはどこかでみたような感じがする形ですね。

さらに、現状の図をScalaで定義してみるとこんな感じになります。

trait Category {
  //対象(ドメイン)
  type Person
  //対象(コドメイン)
  type Job
  //射
  def func:Person => Job
}

しかし、これはまだ圏の条件を満たしていないので、圏とは呼べません。

ここまでのまとめ

ここまでのまとめをしましょう。

  • 圏とは、対象と射で構成されるものである
  • 圏とは、対象同士が射で接続されているものが集まったグループである

今回は圏論の用語について、重要と思われるキーワードをいくつか確認しました。
次回は、圏を構成する射について、もう少し見てみましょう。

参考サイトなど