MathLabs

数学の基礎

圏と関手

圏とは、対象とその間の射を、結合律と単位律だけに従ってまとめたものである。関手とはそのような二つの世界の間の構造を保つ翻訳であり、「物がどう関係しているか」を固定すれば、対象自体は一意な同型を除いて決まることが分かる。

直観同じ形、違う衣装

翻訳者、グラフ、路線でつながる駅の網、「先に起こらなければならない」で結ばれた作業の集合——これらはすべて一つの骨格を共有している:いくつかのもの(対象)と、それらの間をつなぎ連結できる矢印である。圏はその骨格を精密にし、関手はそのような網をもう一つの網の中に、矢印の連結をすべて保ったまま描き直す方法である。

対象とその間の合成可能な矢印を示す対話的な網の図。
対象をノード、射を有向辺として表す;連続する二つの辺を合成すると三つ目の辺が得られる。これこそ圏が記録するデータである。

大学圏:対象、射、合成

定義: 圏

圏 C\mathcal{C} とは、対象 A,B,C,…A, B, C, \dots の集まりと、各対に対する射の集合 HomC(A,B)\mathrm{Hom}_{\mathcal{C}}(A,B)、そして f:A→Bf : A \to B と g:B→Cg : B \to C を g∘f:A→Cg \circ f : A \to C に送る合成規則、さらに各対象に対する恒等射 1A:A→A1_A : A \to A からなるものである。

h∘(g∘f)=(h∘g)∘fh \circ (g \circ f) = (h \circ g) \circ f

二つの公理がこのデータを圏にする:合成が結合的である(h∘(g∘f)=(h∘g)∘fh \circ (g \circ f) = (h \circ g) \circ f、ゆえに矢印の連鎖はどこに括弧を置いても一つの明確な合成を持つ)こと、そして単位射が中立である(1B∘f=f=f∘1A1_B \circ f = f = f \circ 1_A、ゆえに 1A1_A や 1B1_B と合成しても射は変わらない)ことである。

1B∘f=f=f∘1A1_B \circ f = f = f \circ 1_A
共変関手と反変関手
種類射への作用典型例
共変f:A→Bf : A \to B を F(f):F(A)→F(B)F(f) : F(A) \to F(B) に送る、同じ向きリスト関手、忘却関手
反変f:A→Bf : A \to B を F(f):F(B)→F(A)F(f) : F(B) \to F(A) に送る、逆向き双対空間関手、前層Hom(-,A)

発展関手と自然変換

関手 F:C→DF : \mathcal{C} \to \mathcal{D} は、C\mathcal{C} の各対象 AA に D\mathcal{D} の対象 F(A)F(A) を、各射 ff に射 F(f)F(f) を割り当て、合成と単位を保つ:F(g∘f)=F(g)∘F(f)F(g \circ f) = F(g) \circ F(f) かつ F(1A)=1F(A)F(1_A) = 1_{F(A)}。二つの関手 C→D\mathcal{C} \to \mathcal{D} の間の自然変換 η:F⇒G\eta : F \Rightarrow G は、各対象 AA に D\mathcal{D} における射 ηA:F(A)→G(A)\eta_A : F(A) \to G(A) を割り当て、自然性四角形に従う:すべての f:A→Bf : A \to B に対して G(f)∘ηA=ηB∘F(f)G(f) \circ \eta_A = \eta_B \circ F(f)。

F(g∘f)=F(g)∘F(f)F(g \circ f) = F(g) \circ F(f)
G(f)∘ηA=ηB∘F(f)G(f) \circ \eta_A = \eta_B \circ F(f)

T1T_1 と T2T_2 が共に C\mathcal{C} の終対象である(すべての対象からそれぞれへの射がちょうど一つ存在する)とき、T1≅T2T_1 \cong T_2:両者の間に同型が存在し、それは T1→T2T_1 \to T_2 の唯一の射である。双対の命題は始対象について成り立ち、同じ議論を候補錐の圏に適用すれば積についても成り立つ。

なぜ正しいのか?

この事実がなければ「終対象」や「積」が一意に定まらない——積の異なる構成(順序対か別の符号化か)は互換でなければならず、一意な同型を除いた一意性こそがそれらが「同じである」ことの正確な意味である。

証明

T2T_2 が終対象であるため、すべての対象——特に T1T_1——からそこへの射がちょうど一つ存在する。それを u:T1→T2u : T_1 \to T_2 と呼ぶ。T1T_1 が終対象であるため、対称的にちょうど一つの v:T2→T1v : T_2 \to T_1 が存在する。

合成 v∘u:T1→T1v \circ u : T_1 \to T_1 を考える。T1T_1 が終対象であるため、T1→T1T_1 \to T_1 の射はちょうど一つしかなく、1T11_{T_1} はそのような射の一つである。v∘uv \circ u も T1→T1T_1 \to T_1 の射であるため、一意性から v∘u=1T1v \circ u = 1_{T_1} が強制される。

T2T_2 の終対象性を使った対称的な議論により、合成 u∘v:T2→T2u \circ v : T_2 \to T_2 も 1T21_{T_2} に等しくなければならない:u∘v=1T2u \circ v = 1_{T_2}。

両側逆射を持つ射は定義により同型であるから、uu は逆射 vv を持つ同型 T1≅T2T_1 \cong T_2 である。それが T1→T2T_1 \to T_2 の唯一の射であるのは、T2T_2 の終対象性がそもそもそのような射がちょうど一つしかないと述べているからである——uu は最初から一意に決まっており、それが可逆であることが分かっただけである。

F:C→DF : \mathcal{C} \to \mathcal{D} が関手であり、f:A→Bf : A \to B が C\mathcal{C} における逆射 g:B→Ag : B \to A を持つ同型であるとき、F(f):F(A)→F(B)F(f) : F(A) \to F(B) は D\mathcal{D} における同型であり、逆射は F(g)F(g) である。

なぜ正しいのか?

これが関手を信頼できる翻訳者にする理由である:関手は同値を誤って二つの本当に異なる対象に分解することは決してなく、対象を「同型を除いて」分類するという問いを関手は尊重する。

証明

ff と gg が互いに逆であるため、g∘f=1Ag \circ f = 1_A かつ f∘g=1Bf \circ g = 1_B。

最初の等式に FF を適用する。関手は合成を保つので F(g∘f)=F(g)∘F(f)F(g \circ f) = F(g) \circ F(f);関手は単位射を保つので F(1A)=1F(A)F(1_A) = 1_{F(A)}。これらを g∘f=1Ag \circ f = 1_A と組み合わせると F(g)∘F(f)=1F(A)F(g) \circ F(f) = 1_{F(A)} が得られる。

同様に第二の等式に FF を適用する:F(f∘g)=F(f)∘F(g)F(f \circ g) = F(f) \circ F(g) かつ F(1B)=1F(B)F(1_B) = 1_{F(B)} なので、f∘g=1Bf \circ g = 1_B から F(f)∘F(g)=1F(B)F(f) \circ F(g) = 1_{F(B)} が得られる。

この二つの式は、F(g)F(g) が F(f)F(f) の両側逆射であることをまさに述べている。両側逆射を持つ射は同型であるから、F(f):F(A)→F(B)F(f) : F(A) \to F(B) は逆射 F(g)F(g) を持つ同型であり、主張どおりである。

大学応用:関数型プログラミングとデータベース移行

主要な関数型言語がすべて `Functor` 型クラスを持つのは、リストや木、`Maybe`/`Option` のようなコンテナが、型と関数の圏上の関手であるからにほかならない:`fmap` は射に対する FF であり、関手則 fmap id=id\mathrm{fmap}\,\mathrm{id} = \mathrm{id}、fmap (g∘f)=fmap g∘fmap f\mathrm{fmap}\,(g \circ f) = \mathrm{fmap}\,g \circ \mathrm{fmap}\,f はまさに上の公理である。`Monad` はさらに二つの自然変換(`return` と `join`)を用いて、自然性四角形に似た整合律を課すことで精緻化する。プログラミングの外では、David Spivakの関手的データ移行が、データベーススキーマを小さな圏(テーブルを対象、外部キーを射)としてモデル化し、スキーマ移行を二つのそのような圏の間の関手としてモデル化する。「データを正しく移動する」ことは文字通り「関手であること」を意味し、合成保存性により、中間スキーマを経由した移行が直接の移行と同じ結果を与えることが保証される。

例: リストに対する関手則の検証

リストに対する fmap\mathrm{fmap} を、すべての要素に関数を適用するものとして定義する:fmap f [x1,…,xn]=[f(x1),…,f(xn)]\mathrm{fmap}\,f\,[x_1,\dots,x_n] = [f(x_1),\dots,f(x_n)]。具体的なリスト [1,2,3][1,2,3] に対し、f(x)=x+1f(x)=x+1、g(x)=2xg(x)=2x で両方の関手則を検証せよ。

解答

法則一、fmap id=id\mathrm{fmap}\,\mathrm{id} = \mathrm{id}:恒等関数を各要素に適用すると fmap id [1,2,3]=[id(1),id(2),id(3)]=[1,2,3]\mathrm{fmap}\,\mathrm{id}\,[1,2,3] = [\mathrm{id}(1),\mathrm{id}(2),\mathrm{id}(3)] = [1,2,3] となり、これはまさに id [1,2,3]\mathrm{id}\,[1,2,3] である。これはこのリストだけでなく任意のリストで成り立つ。各要素に「何もしない」を適用してもリストには何も起こらないからである。

法則二、fmap (g∘f)=fmap g∘fmap f\mathrm{fmap}\,(g \circ f) = \mathrm{fmap}\,g \circ \mathrm{fmap}\,f:まず左辺を計算する。(g∘f)(x)=2(x+1)(g \circ f)(x) = 2(x+1) なので、fmap (g∘f) [1,2,3]=[2⋅2,2⋅3,2⋅4]=[4,6,8]\mathrm{fmap}\,(g\circ f)\,[1,2,3] = [2\cdot2, 2\cdot3, 2\cdot4] = [4,6,8]。

次に右辺:fmap f [1,2,3]=[2,3,4]\mathrm{fmap}\,f\,[1,2,3] = [2,3,4]、続けて fmap g [2,3,4]=[4,6,8]\mathrm{fmap}\,g\,[2,3,4] = [4,6,8]。

両辺とも [4,6,8][4,6,8] に等しく、この例で法則が確認された;一般的な証明は 1,2,31,2,3 の代わりに xix_i を用いた同じ計算であり、fmap\mathrm{fmap} が要素を並べ替えたり落としたりすることが決してないからである。

例: 関手としてのスキーマ移行

スキーマ S1\mathcal{S}_1 にはテーブル `Person` と `City` があり、外部キー `livesIn : Person -> City` を持つ。新しいスキーマ S2\mathcal{S}_2 は `Person` を `Person` と `Contact` に分割し、`hasContact : Person -> Contact` と `livesIn2 : Contact -> City` を持つ。この移行を関手として記述し、合成保存が何をもたらすか説明せよ。

解答

各スキーマを圏としてモデル化する:対象はテーブル、射は自由に合成される外部キーである(したがって S1\mathcal{S}_1 には生成子として合成 livesIn:Person→City\texttt{livesIn} : \texttt{Person} \to \texttt{City} がある)。移行 F:S1→S2F : \mathcal{S}_1 \to \mathcal{S}_2 は Person↦Person\texttt{Person} \mapsto \texttt{Person}、City↦City\texttt{City} \mapsto \texttt{City} を送り、射 livesIn\texttt{livesIn} を S2\mathcal{S}_2 における合成射 livesIn2∘hasContact:Person→City\texttt{livesIn2} \circ \texttt{hasContact} : \texttt{Person} \to \texttt{City} に送る。

FF が関手であるためには単位射を単位射に送り(ここでは自明)、合成を尊重しなければならない:S1\mathcal{S}_1 で livesIn\texttt{livesIn} から作られる外部キーの連鎖は、F(livesIn)=livesIn2∘hasContactF(\texttt{livesIn}) = \texttt{livesIn2} \circ \texttt{hasContact} から作られる同じ連鎖に、同じ順序で、飛ばしや並べ替えなしに写らなければならない。

これこそ「関手は合成を保つ」という定理がエンジニアにもたらすものである:古いスキーマで livesIn\texttt{livesIn} を介して Person\texttt{Person} を City\texttt{City} に結合するクエリがあるとき、各テーブルを翻訳し livesIn\texttt{livesIn} を二段階の経路に写してから結合を実行すれば、クエリ全体を一つの単位として翻訳した場合と同じ答えが得られる——テーブル単位で移行したデータは、クエリ単位で移行したデータと一致することが保証される。まさに F(g∘f)=F(g)∘F(f)F(g \circ f) = F(g) \circ F(f) であるからである。

どの二つの方程式が圏の二つの公理か?

反変関手は f:A→Bf : A \to B をどちら向きの射に送るか?

Spivakの関手的データ移行において、スキーマ移行は何に対応するか?

u:T1→T2u : T_1 \to T_2 が二つの終対象の間の唯一の射であるとき、定理は uu について何を述べるか?

参考文献

  1. Saunders Mac Lane (1998). Categories for the Working Mathematician
  2. Emily Riehl (2016). Category Theory in Context
  3. David I. Spivak (2012). Functorial Data Migration · arXiv:1009.1166