Google ClassroomGoogle Classroom
GeoGebraClasse GeoGebra

圏論には「ファンクター」から入ろう

このページはマス旅の一部です。 「圏」は「集合」と「ベクトル」と「群」をゆる~くアレンジしてできた、 何かのつながりを俯瞰するときに使える数学のアイディアです。 知らないものを学ぶという感覚ではなく、 ぼんやり気づいていることの明確化だ、と思って付き合いましょう。 さて、「圏」は「集合」と「ベクトル」と「群」をゆる~くアレンジしてできたものとかきましたが、 ざっくり、「圏」(カテゴリー)というカタマリの共通ルールを確認しましょう。 そして、1つめキーワードである「ファンクター(関手)」に親しもう。

6の約数圏

1.圏の具体と抽象

圏の具体と抽象 <圏とは何か> 「圏」とは、対象と「射」という矢印を持っていて、1という矢印があり、 矢印の結合ができて、結合法則が成り立つ、そういうカタマリです。 たったこれだけのルールです。 対象があるところが「集合」と同じだけど、その中身は特に指定されてない。対象は数どころか、同種のものがあつまってれば何でもOK。 矢印があるのが「ベクトル」と同じだけれど、始点と終点はあっても位置はない、長さは自由。 1と結合法則については「群」と同じだけれど、逆は特になくてOK。 ここまで読んで、どう思いますか。 矢印中心で対象はあいまいです。これでいいのか? と思いますよね。あえて、矢印中心にしたのです。 これが「圏」の物重視ではな関係重視の思想です。internalよりもexternal重視です。 矢印の位置も長さがどうでもよくて、つなげ方が大事です。 これが、同型なら同じとみなすという位相的な発想が基本にあります。 「射」中心の圏論では、対象を同型を除いて(up to isomorphism)区別するのが自然なのです。 <圏の具体> 人間の認知構造として、モデルがないと、わかった気にならないものです。 そこで、圏の具体を並べます。 ヒットするものがあるとうれしいです。 圏の名前={対象、射、結合、1} の順に並べてみますね。 整数の整除圏={整数たち、整除、整除の連続、自身を割る} 半順序圏={半順序集合の要素、半順序 、半順序の合成、自身との半順序」 6の約数圏={[1,2,3,6]、xはyの約数、約数の約数、1} 先祖圏={[私、母、祖母]、xはy以上の先祖、先祖の先祖、自身} Grps(群圏)={群たち、群準同型、群準同型の合成,恒等写像} Sets(集合圏)={集合たち、写像、写像の合成、恒等写像} Tops(位相空間圏)={位相空間たち、連続写像、写像の合成、恒等写像} 空圏={空、空、空、空} 1圏={1、1→1、1、1} グラフ圏={ノード、矢、矢をつなぐ、自己ノードをさすループ} データ型圏={データ型たち(数値、文字列、リスト)、型変換、変換の連続、無変換} すごろく圏={すごろくの位置(振り出し、とちゅう、ゴール)、進む、進むを続ける、休み} まだまだありそうですね。 半群の圏、環の圏、体の圏、....... 集合で対象を1つの集合の要素たちにして、射を部分集合にした「部分集合の圏」もできるでしょう。 集合たちでも2つの集合の共通部分を射にすると、「共通部分の圏」もできるでしょう。 いろいろできそうですね。 「圏」のアイディアが「普遍性」のあるものだということが感じられるでしょう。 さて、次はいよいよ、 圏と圏をつなぐ矢印であるファンクター(関手) を見てみよう。

2.ファンクターはこわさず持ち上げる

<ファンクターはこわさず持ち上げる> functorはfunctionと最初の4文字が同じです。 働きは似てますが、厳密には違うからこそ違う名前がついています。 見慣れないコトバだと思っている人には朗報です。 「ファンクターはセットメニュー化」 というブンゲン先生の「はじめての圏論」でのたとえが超わかりやすいです。 H=ハンバーグ圏 ={[ハンバーグ、チーズハンバーグ、和風ハンバーグ、…]、 [和風にする、チーズをのせる、...]、 射を組み合わせる、素のまま} fmap(H)=ハンバーグライスセット圏 ={[ハンバーグライスセット、チーズハンバーグライスセット、和風ハンバーグライスセット、…]、[和風にする、チーズをのせる、...]、射を組み合わせる、素のまま} ここで、Hの2つの対象a=ハンバーグ、 b=チーズハンバーグと、射cheeze:a→b(チーズをのせる)を とりあげましょう。 f(a),f(b)の関係はcheezeなので、fmap(cheeze):f(a)→f(a)ですよね。 HaskellのFunctorの型クラスの定義は次のようになってます。 class Functor f where fmap f :: (a->b) -> fa -> fb (Haskellは関数の引数にかっこをつけないの上にかいたことと同じです。) 射をまるごと始点と終点もいっしょに移しますが、始点、終点はライスセットのfが効いてますが、 射のチーズをのせるのはそのまま保存されてますね。 Functorの型には、Maybeというインスタンスもあります。 Maybeはたぶんコケるかもというデータ型です。 こけても安全にデータとして渡されます。 「fmap」はmapだけどファンクターのマッピングですよという、 一般のmapと区別するためのワードですので深入りしないでいいです。 「where」はHaskellの条件句の開始部分で左カッコ程度の意味ですね。 instance Functor Maybe where fmap f (Just x) = just (f x) fmap f Nothing = Nothing 似たものにEitherというインスタンスもあります。 instance Functor (Either a) where fmap f (Right x) = Right (f x) fmap f (Left x) = Left x Haskellは型が厳密な言語なので、ファンクター型が種類わけされています。 Pythonとは現状真逆で型にうるさくないなのでFunctorはもっとゆるく使えましたね。 たとえば、PythonのFunctorのMaybeの使い方は、 from pymonad.maybe import Just, Nothing def extract_addressM(X): return Just(X["A"]) if "A" in X else Nothing というように、 辞書型のデータのaddress項目を調べて、欠損してないとJustでくるみ、欠損してるとNothing を返す。JustもNothingも予定された値だから欠損値でもエラーがおきずに動かせます。 Nothingじゃあさみしいと思ったら、 def extract_addressE(X): return Right(X["address"]) if "address" in X and X["address"] is not None else Left("Address がありません") Either型を使って、欠損値のときはLeftにメッセージをくるみ、データがあればRightにくるんで送ります。 これは、単独処理ではなく、複数の項目があればこのような関数をバケツリレーできます。 変なデータがまざっていても、エラーが起きずに情報収集ができます。 くわしくは、こちら「FP:モナドで現実データ世界を安全に過ごそう」をご覧ください。 <振り返り> 今の3つの例からわかることは何でしょう。 ブンゲン先生の例は 「ハンバーグ圏」の構造を持ち上げて「ライスセット圏」を作りました。 Maybeは 「データ圏」の構造を変えずに、「Maybe圏」を作りました。 Eitherは 「データ圏」の構造を変えずに、「Either圏」を作りました。 これって、圏を圏に移す射です、1対1で構造を壊さず全体を持ち上げてますね。 ということは ファンクター={圏たち、ファンクター、合成、恒等射}という圏になっているということですね。 このしくみは、 2の約数圏={[1,2]、約数、合成、自分自身の約数}という超シンプルな圏と対応がつくね。 ファンクターを使うと、圏の同型写像の圏を作れそうですね。 だた、準同型ではなく、同型といえるためには逆戻りできないといけない。 厳密には、逆射としての逆ファンクターが構成できると、「圏同型」と言えそうだね。また、ファンクターは射の1つだから、 射の合成としてファンクターのバケツリレーができるということも言えるでしょう。 たとえば、「ライスセット圏」にビールをつけて「ビールライスセット圏」もできるでしょう。 <さらに俯瞰しよう> 圏たちが、対象でファンクターが射となる圏が作れるということは、 圏と圏をつなぐファンクターを複数用意することができるはずだ。 さっきの例では、 1つのデータ圏に対して、ファンクターを変えたために、Maybe圏とEiger圏ができた。 でも、圏Cに2つのファンクターF,Gをして同じ圏Dができることもありうるでしょう。 そうすると、F、Gは違ってみえても、 2つのファンクターFをGに翻訳する対応が自然にできるはずですね。 これを自然変換(natural transformation)という。 圏Cの中の射f:a→bに目をつけてみよう。 射がそれぞれ持ち上げられるとして、F(f): F(a)→F(b)とG(g):G(a)→G(b)とする。 そして、FモノからGモノへの翻訳をφとしたら、 F(a)からG(b)への射は φaしてG(f)でも、F(f)してからφbしても同じはずだ。 これを「図式が可換」だという言い方をします。 圏論の証明の基本技です。 群論の証明でもよく出てきましたね。 グラフをかくと、四角形ABCDができてて、AからCへの矢印は AB+BCでも、AD+DCでも射の合成は同じになりますよ というものでしたね。 イメージとしたら、「ビールライスセット圏」は ピールが先でもライスが先でも、 結局は、「ビールライスセット圏」ができるでしょということですね。

3.圏の視覚化

圏の視覚化をしてみる。 課題:自然変換φの図式が可換であることを視覚化しよう。 #Pythonを使わなくても、geogebraで図式がカンタンにかけます。 #オブジェクトの設定のラベルの変更によって、記述の自由度があがりますね。 #タイトル「自然変換φの図式が可換」 #四角形ABCDをかきます。 A=(-3,3) B=(-3,-1) C=(3,-1) D=(3,3) φa=Vector(A,B) φb=Vector(D,C) Ff=Vector(A,D Gf=Vector(B,C) 4点A,B,C,Dの設定を順にひらいて ラベルをF(a),G(a),G(b),F(b)に変更します。 ビューの格子と軸を設定で非表示にすると、図に見えますね。

自然変換φの図式が可換

課題:データ圏をMaybe圏やEither圏に持ち上げるようすを視覚化しよう。 Pythonを使わなくても、geogebraでカンタンに作れます。 #タイトル「データ圏をファンクターを使って、Maybe圏またはEither圏へ持ち上げる」 a=slider(-10,10,1) #アニメーションにする。 JorN={"Just " + a, "Nothing"} Maybe=if(a>=0, JorN(1), JorN(2)) #太字で青で文字サイズを大にする。 RorL={"Right( " + a + " )","Left(負のデータです)") Either= if(a>=0, RorL(1), RorL(2)) #太字で緑で文字サイズを大にする。 b=CheckBox(if(On),Maybe,Either) #Maybeに連動して作る。Eitherの設定で上級でb==falseとする。 ビューの格子と軸を設定で非表示にすると、図に見えますね。

データ圏をファンクターを使って、Maybe圏またはEither圏へ持ち上げる