このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

アイレンベルグ/ムーア圏 その3:Maybeモナドのとき

アイレンベルグ/ムーア圏 その1」において、アイレンベルグ/ムーア圏の定義を述べ、「アイレンベルグ/ムーア圏 その2:リストモナドのとき」で典型的な事例を紹介しました。さらに別な例を挙げます。今日は、Maybeモナドアイレンベルグ/ムーア圏がどんな圏になるかを調べてみます。

内容:

Maybeモナド(付点モナド

C上のモナドを (M, η, μ) として、「アイレンベルグ/ムーア圏 その2:リストモナドのとき」と同じような書き方でMaybeモナドを定義しておきます。

  1. C := Set
  2. M0(A) := Maybe<A> := A + 1
  3. M1(f:A→B) :=Maybe.lift<A, B>(f):(A + 1)→(B + 1)
  4. ηA := Maybe.embed<A>:A→(A + 1)
  5. μA := Maybe.join<A>:((A + 1) + 1)→(A + 1)

1は特定された単元集合(singleton set)です。1の唯一の要素は何でもいいのですが、⊥(ボトム)記号にしておきます。Maybe<A> := A + 1 なので、Maybe<A> := A + {⊥} です。注意すべきは、+ が直和(排他的な合併)を表すので、⊥!∈A (!∈ は「∈の否定」)を前提としていることです。Aには属さないナニカを取ってきて、それをAに追加するわけです*1。(A + 1) + 1 は、(A + {⊥}) + {⊥} ですが、これは A + {⊥} ではなくて、A + {⊥1, ⊥2} のように考えます。

lift, embed, joinは、なんか無理矢理に名前を付けた感じですが、次のような定義になります。

  • for-all x in A { Maybe.lift<A, B>(f)(x) = f(x) }, Maybe.lift<A, B>(⊥) = ⊥
  • for-all x in A { Maybe.embed<A>(x) = x }
  • for-all x in A { Maybe.join<A>(x) = x }, Maybe.join<A>(⊥1) = ⊥, Maybe.join<A>(⊥2) = ⊥

最後のMaybe.joinは、2つのボトムを1つのボトムにまとめるものです。次の図のような雰囲気です。

こうして定義されたMaybeモナドは、与えられた集合Aに1点を追加する操作なので、付点モナドと呼んでもいいでしょう。

Maybeモナドの代数

C上のモナド (M, η, μ) の代数とは、とりあえずは a:M(A)→A in C という射でした。Maybeモナドの場合は、a:(A + {⊥})→A となります。代数が満たすべき条件は次の図が可換になることでした。

  A - η_A --> M(A)
  |            |
  |            a
  |            |
  v            v
  A ---------> A

  M(M(A)) - M(a) --> M(A)
   |                  |
  μ_A                a
   |                  |
   v                  v
  M(A) ----- a -----> A

MがMaybeモナドのときに等式で書き下せば:

  1. for-all x in A { a(Maybe.embed<A>(x)) = x }
  2. for-all z in (A + {⊥1, ⊥2}) { a(Maybe.lift<Maybe<A>, A>(a)(z)) = a(Maybe.join<A>(z)) }

以下で、これらの等式を噛み砕いて分析してみましょう。

Maybeモナドの代数の単位律

Maybe代数の重要な性質は一番目の等式から出てきます。

  • for-all x in A { a(Maybe.embed<A>(x)) = x }

Maybe.embedの定義 Maybe.embed<A>(x) = x を使うと:

  • for-all x in A { a(x) = x }

となります。代数の演算aは、A + {⊥} 上で定義されていたので、a(⊥) = e (e∈A) と置きましょう。すると、aは次のように記述できます。

  1. a(x) = x if x in A
  2. a(⊥) = e (e∈A)

結局、Maybeモナドの代数 (A, a) は、Aの一点であるeを指定すれば決まることになります。そこで、Maybe代数を、「集合Aと演算aの組」ではなくて、「集合AとAの一点eの組」で表すこともできます。(A, e) ですね。(A, e) から (A, a) を再現するには、すぐ上のようにaを定義すればいいのです。

Maybeモナドの代数の結合律

次に二番目の等式です。

  1. for-all z in (A + {⊥1, ⊥2}) { a(Maybe.lift<Maybe<A>, A>(a)(z)) = a(Maybe.join<A>(z)) }

二番目の等式は面倒そうですが、A + {⊥1, ⊥2} = (A + {⊥1}) + {⊥2} として、A + {⊥1} の部分と {⊥2} に分けてみると次のようです。

  1. for-all y in (A + {⊥1}) { a(Maybe.lift<Maybe<A>, A>(a)(y)) = a(Maybe.join<A>(y)) }
  2. a(Maybe.lift<Maybe<A>, A>(a)(⊥2)) = a(Maybe.join<A>(⊥2))

一番目をさらに分解すると:

  1. for-all x in A { a(Maybe.lift<Maybe<A>, A>(a)(x)) = a(Maybe.join<A>(x)) }
  2. a(Maybe.lift<Maybe<A>, A>(a)(⊥1)) = a(Maybe.join<A>(⊥1))
  3. a(Maybe.lift<Maybe<A>, A>(a)(⊥2)) = a(Maybe.join<A>(⊥2))

どうにもクソ鬱陶しい等式群ですが、Maybe.による修飾や型パラメータを省略すると多少はスッキリします*2

  1. for-all x in A { a(lift(a)(x)) = a(join(x)) }
  2. a(lift(a)(⊥1)) = a(join(⊥1))
  3. a(lift(a)(⊥2)) = a(join(⊥2))

絵を描けば、これらの等式がたいした内容を持たないないことが分かるでしょう。

実際、定義に従って計算すると、等式は次のように簡略化されます。

  1. for-all x in X { a(x) = a(x) }
  2. a(a(⊥1) = a(⊥)
  3. a(⊥) = a(⊥)

一番目と三番目はまったくのトートロジー、二番目は a(e) = e ですが、これも新しい事実ではありません。つまり、Maybeモナドに関して言えば、結合律から新しい情報は何も出てきません。別な言い方をすると、Maybe代数は単位律だけの制約を受けるということです。

付点集合の圏

付点集合(pointed set; 基点付き集合)とは、集合Aにその一点eが指定されたものです。付点集合を (A, e) で表しますが、e∈A であることを強調して、(A, eA) とも書きます。さらには、記号の乱用で A = (A, eA) のようにも書きます。

(A, eA), (B, eB) が2つの付点集合のとき、写像 f:A→B が、f(eA) = eB であるとき、付点集合のあいだの射だとします。付点集合とその射の全体は圏をなします。その圏をPtSetとしましょう。空集合は基点を持てないので付点集合とはならないことに注意してください。

Mabyモナド(付点モナド)の代数 (A, a) があると、(A, a(⊥)) という付点集合を定義できます。逆に、付点集合 (A, eA) があれば、a(⊥) = eA (その他部分は恒等)としてMaybe代数が定義できます。

f:A→B がMayb代数の射 (A, a)→(B, b) であるとは次の図式が可換になることです。

 Maybe<A> - a --> A
   |              |
  lift(f)         f
   |              |
   v              v
 Maybe<b> - b --> B

a(⊥A) = eA ∈A, b(⊥B) = eB ∈B とすると、この可換図式から f(eA) = eB が従います。つまり、fは付点集合の射 (A, eA)→(B, eB) を定義します。逆向きの対応も作れることから、Maybeモナドアイレンベルグ/ムーア圏 EM(Set, Maybe) は、付点集合の圏PtSetと圏同値になります。



不思議なことに、有名なモナドアイレンベルグ/ムーア圏を作ると、よく知られた圏が現れます。EM(Set, List) = Mon(Set) と EM(Set, Maybe) = PtSet という圏同値が登場しましたが、他の例でもお馴染みの圏が再現されることが多いようです。実際には、この現象は不思議でもなんでもなく、同じ実体を別な側面から見ているだけのことかも知れませんけどね。

*1:ちょっと技巧的ですが、A∈A は成立しないことが保証されているので、⊥A := A として、A + {⊥A} = A∪{A} とすれば安全です。「Aには属さないナニカ」の取り方は他にもありますので、あまり気にしない方向で。

*2:型パラメータを明示的に書くプログラミング言語風の記法が、圏論の記述には向いてないのかも知れません。圏論に最適化された記法や絵図を使うと、もっと単純な記述ができます。