モナドとコモナド
逆演算という概念を導入するために、積コモナドという道具を使いました。このコモナドというのは圏論の概念で、モナドの双対概念として登場します。これらを数学に導入する意義はいくつかあるのですが、ここでは、型の条件から合成できそうにないものについて、合成を定義できることくらいにとらえるといいと思います。モナドとコモナドの定義は、2つの操作と2つ条件からなります。逆演算の記事では、条件については触れませんでした。
ただし、ここで紹介するのは、歴史的にはクライスリトリプルというもので、モナドの通常の定義(単位元+乗法)とは異なっているので注意してください。
ただし、ここで紹介するのは、歴史的にはクライスリトリプルというもので、モナドの通常の定義(単位元+乗法)とは異なっているので注意してください。
積コモナド
集合Xを任意に固定します。このとき、各集合Aに対して積A × Xを考えることができます。これに次の2つの操作を加えたものが、集合Xが与える積コモナドです。
・余単位元ε
任意の集合Aに対して、εA : A × X → A を次のように定義する。
\[ ε_A (a, x) = a \]
・余拡張†
任意の関数f : A × X → B に対して、f† : A × X → B × X を次のように定義する。
\[ f^†(a, x) = (f(a, x), x)\]
合成
これらの操作を考えることの意義は関数の合成を考えることができることです。関数f : A × X → B と 関数 g : B × X → C が与えられたとき、素朴に考えればf と g を合成することはできません。f の 余ドメイン(B)と g のドメイン(B × X)が等しくないからです。このようなとき、余拡張を使うと次のように合成することができます。
\[g \circ f^† : A × X → C \]
これはfを余拡張することで、fの余ドメインがB×Xになりgのドメインと一致するからです。A × X の値(a, x)を与えると次のようになります。
\[g \circ f^† (a, x) = g(f(a, x), x)\]
以上のことは「逆演算について」で触れたことです。しかし、これらがきちんと「合成」の条件を満たしていることを確かめなければなりません。
合成の条件
通常の関数の合成については恒等関数の単位元性と結合法則という2つの条件が必要です。
・恒等関数の単位元性\[ f \circ id_A = f = id_B \circ f \]
・結合法則
\[(h \circ g) \circ f = h \circ (g \circ f) \]
恒等関数というものが通常の関数にはありますが、積コモナドにおいてこれに相当するものが余単位元です。積コモナドではこれらの条件に対応する条件があります。
・余単位元の単位元性
\[ f \circ ε_A^† = f = ε_B \circ f^†\]
これは次のように言い換えられます。
\[ε_A^† = id_{A×X} \]
・結合法則
\[(h \circ g^†) \circ f^† = h \circ (g \circ f^†)^† \]
これは次のように言い換えられます。
\[g^† \circ f^† = (g \circ f^†)^† \]
それぞれの条件について簡潔に言い換えたものを加えました。コモナドは圏論で定義される概念ですが、実はこの簡潔な条件の方が、コモナドの条件になっています。簡潔な条件の方が証明などにおいて簡単ですが、意味的にはわかりにくいので、あえて、関数の合成の条件に類比させて述べておきました。証明は簡単なのでここでは省略します。
コモナドの条件
さきほどの合成の条件をコモナドの条件として整理します。余単位元と余拡張は次の2つの条件を満たしていなければなりません。
\[ε_A^† = id_{A×X} \\ g^† \circ f^† = (g \circ f^†)^† \]
ベキモナド
モナドの例もここで紹介しましょう。各集合Aについてその冪集合Pow(A)を考えることができ、次の2つの操作が与えられます。
・単位元
任意の集合Aに対して、ηA : A → Pow(A) を次のように定義する。
\[ η_A (a) = \{a\} \]
\[ η_A (a) = \{a\} \]
・拡張
任意の関数f : A → Pow(B) に対して、f# : Pow(A) → Pow(B) を次のように定義する。
\[ f^# (A') = \bigcup_{a \in A'}f(a) \]
\[ f^# (A') = \bigcup_{a \in A'}f(a) \]
合成
関数f : A → Pow(B) と 関数 g : B → Pow(C) が与えられたとき、合成は次のように定義します。
\[ g^# \circ f : A → \mathcal{P}(C) \]
Aの値aを与えると次のようになります。
\[ g^# \circ f (a) = \bigcup_{b \in f(a)}g(b)\]
合成の条件
合成の条件は次のようになります。2つの表現で書かれているのは、先ほどの合成との類比と簡潔なものです。
・単位元の単位元性
\[ f^# \circ η_A = f = η_B^# \circ f \\
η_A^# = id_{\mathcal{A}} \]
・結合法則
\[(h \circ g)^# \circ f = h^# \circ (g^# \circ f) \\ (h \circ g)^# = (h^# \circ g)^# \]
\[ f^# \circ η_A = f = η_B^# \circ f \\
η_A^# = id_{\mathcal{A}} \]
・結合法則
\[(h \circ g)^# \circ f = h^# \circ (g^# \circ f) \\ (h \circ g)^# = (h^# \circ g)^# \]
プログラミングにおけるモナド
HaskellではMaybeモナドというものが標準で用意されています。これは、次のような方です。
Maybe a ::= Just a | Nothing
これを使うと、たとえばaからbへの部分関数fを次のように表現できます。
f :: a -> Maybe b
f x | defined = Just f(x)
| undefined = Nothing
モナドを使うと、これらを合成することができます。Maybeモナドの単位元と拡張は次のようなものです。
・単位元
return :: a -> Maybe a
return x = Just x
・拡張
f :: a -> Maybe b に対して、 >>=f :: Maybe a -> Maybe b は次のような関数です。
(>>=f) Just x = f(x)
Nothing = Nothing
これらもモナドの条件を満たします。
参考文献
モナド・コモナドについては、次のものが参考になると思います。
・数学セミナー2011.12 圏論の歩き方(第5回)モナドと計算効果 勝股 審也
また、積コモナドについては、次のものを参考にしました。
補足
積コモナドは逆演算を定義するために導入したもので、逆演算については次の記事を見てください。
逆演算について
≪…モナドの双対概念…≫を、代数学と解析学の双対性で自然数を観る。
返信削除双対性は、
離散性 ⇔ 連続性
コスモス ⇔ カオス
とのコトを、『離散的有理数の組み合わせによる多変数創発関数論 Ⅱ 』の帰結と
十進法の基での桁表示の西洋数学の成果の6つのシェーマ(符号)を受け入れると
⦅自然数⦆は、カオスを帯同するコスモスの認識(認知科学)と観える。
認知科学的⦅自然数⦆は、
[絵本]「もろはのつるぎ]で・・・
『HHNI眺望』で観る自然数の絵本あり。
返信削除有田川町電子書籍 「もろはのつるぎ」
御講評をお願い致します。
時間軸の数直線は、『幻のマスキングテープ』に・・・
『かおすのくにのかたなかーど』から・・・