クライスリ・トリプル
クライスリ・トリプル とは次の3つの組み合わせです。
- 自己関手 T
- 拡張演算子 (_)#
- 自然変換 η
拡張演算子は任意の f:X→TY について f#:TX→TY を割り当てます。f:X→TY という射の域(domain)X を TX に拡張しているわけです。
拡張は f:X→TY と g:Y→TZ を合成するために必要です。このままでは f の余域(codomain)と g の域が等しくありませんので、合成ができません。そこで、g を g# に拡張するわけです。すると、g#∘f:X→TY という合成を考えられる。
自然変換 η は単位元と呼ばれます。というのは、拡張によって得られる合成について単位元となるからです。まず、η は次のような自然変換です。つまり、任意の C の対象 X について、
ηX:X→TX
という射を定める。そして、任意の f:X→TY について、
f#∘ηX=f=ηY#∘f
が成り立ちます。等式 f=ηY∗∘f はいささか冗長です。これは、
ηY#=idTY
が与えられれば十分です。
また、拡張によって得られる合成は結合的です。つまり、
h#∘(g#∘f)=(h#∘g)#∘f
です。これもいささか冗長です。そもそも関数合成 ∘ は結合的ですから、
h#∘g#=(h#∘g)#
が与えられば十分です。クライスリ・トリプルの公理を以下のようにまとめましょう。
-
右単位元則: f#∘ηX=f
-
左単位元則: ηY#=idTY
-
結合法則: h#∘g#=(h#∘g)#
関数型プログラミングにおけるクライスリ・トリプル
単位元 η と拡張演算子 (_)# は Haskell の return
と >>=
に対応します。
ただし、f :: a -> m b
です。
クライスリ圏
クライスリ・トリプル ⟨T,(_)#,η⟩ が与えられたとします。このとき、次のように クライスリ圏 と呼ばれる圏を考えられます。
- 対象: C の対象と等しい
- 射: f:X→Y は C 上の射 f:X→TY
- 合成: XfYgZ の合成 g∘f は C 上の XfTYg#TZ の合成 g#∘f
部分写像
写像 f:X→Y とは任意の x∈X について f(x)∈Y が一意に定まるときに与えられます。しかし、ある x∈X については f(x)∈Y が定まらないということもあるでしょう。これを部分写像(partial mapping)といいます。
これを全域で定義された写像と考える方法があります。それが、
f:X→Y+1
と考えるということです。つまり、排他的論理和
f(x)∈Y⊕f(x)∈1
が成り立ちます。定まらないときは、f(x)=0 としてしまうわけです(1={0})。しばしば、f(x)=⊥ と表します。以降はこちらの記法にしましょう。
単位元 η は任意の X について ηX:X→X+1 を以下のように定めます。
ηX(x)=x
つまり、恒等写像を疑似部分写像にしたものです。拡張 f#:X+1→Y+1 は、
f#(x)={f(x)⊥⋯⋯x∈Xx=⊥
部分写像ですから、未定義の値を受け取ればそれを未定義として返すわけです。このクライスリ圏は部分写像の圏となります。
関数型プログラミングでは Maybe
モナドに等しいです。
多価関数
続いては f(x)∈Y が一意に定まらないときを考えます。つまり、f(x) が複数あるようなときです。こちらも、一意写像と考える方法があります。それが、
f(x):X→PY
を考えるという方法です。 ただし、P はべき(power)です。つまり、部分集合全体を余域とするわけです。f(x)∈Y ではなく f(x)⊆Y となります。
単位元 ηX:X→PX は単元集合を返します。
ηX(x)={x}
こちらも恒等写像を擬似多価関数にしたものと考えればよいでしょう。拡張 f#:PX→PY は、
f#(X′)=x∈X′⋃f(x)
になります。受け取った複数の値に対して f(x) の和集合を返すわけです。このクライスリ圏は多価関数の圏になります。
多価関数は二項関係 R⊆X×Y でもあります。そのため、このクライスリ圏は関係の圏でもある。このことについては、また別の記事で詳しく書く予定です。
列(リスト)
多価関数の場合は返値が集合でした。集合とは順序のない集まりと考えられます。つまり、{x,y}={y,x} です。さらに重複も無視します。つまり、{x,y,y}={x,y} です。さて、順序もあり重複も無視しないものを列(list)と呼びます。x∈X の列全体をX∗ と表しましょう。これは直積の閉包
X∗=1+X+X2+X3+⋯
です。これにも多価関数と同様なクライスリ・トリプルを与えられます。単位元は、
ηX(x)=(x)
です。つまり、長さ1の列に返すわけです。そして、f#:X∗→Y∗ は、
f#(x1,x2,⋯,xn)=(f(x1),f(x2),⋯,f(xn))
です。
余クライスリ・トリプル
クライスリ・トリプルの双対を考えることができます。それが、余クライスリ・トリプルです。
- 自己関手 D
- 余拡張演算子 (_)†
- 自然変換 ε
余拡張演算子は余域を拡張します。つまり、f:DX→Y について、
f†:DX→DY
を与えます。余拡張によって得られる合成は、
g∘f†:DX→Z
です。余クライスリ・トリプルの公理は、
-
右単位元則: εX†=idDX
-
左単位元則: εY∘f†=f
-
結合法則: h†∘g†=(h†∘g)†
積
任意の a∈Σ について fa:X→Y が定まるとします。つまり、Σ が添字集合(index set)となっているわけです。これを f:Σ×X→Y と考えることができます。つまり、
f(a,x)=fa(x)
と考えるわけです。添字集合が固定されているとして、たとえば、f:Σ×X→Y と g:Σ×Y→Z を合成したいときに積余クライスリ・トリプルがそれを可能にします。
余単位元 εX:Σ×X→X は射影です。つまり、
εX(a,x)=x
です。これは任意の添字 a∈Σ について (εX)a=idX ということです。余拡張は
f†(a,x)=(a,f(x))
になります。合成するときは、前後で同じ添字を使うことになります。余クライスリ圏では、
f:X→Y と g:Y→Z の合成 g∘f:X→Z は、任意の a∈Σ について、
(g∘f)a=ga∘fa
を考えているということです。
参考文献
Discussion