Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire
注意 この記事はあまり形式的な圏論で記述されてない. 考えてる圏は Hask 圏かもしくはせいぜい Set 圏である. 射のことを関数と書いてあったり, 対象の「要素」なるものを前提なしに取り上げている.
概要
一般の再帰的データ構造について, ちょうど, リストに対する畳み込み (fold) といったような4種類の操作 (catamorphism, anamorphism, hylomorphism, paramorphism) を統一的に与える.
表記
この論文では独特な括弧が4種類導入されている. できるだけオリジナルの見た目を模倣して, ここでは次のように表記する.
バナナ括弧 |
|
(| |) |
果物のバナナ |
レンズ括弧 |
|
[( )] |
凹レンズ |
封筒括弧 |
|
[[ ]] |
|
有刺鉄線 |
|
[< >] |
と の重ねあわせ |
他にこの論文で使われてる表記で次のものをこの文書でも用いる.
-
- 型 の値 (或いは ) と任意の型 (集合) について, なる定数関数のこと
またこの論文で使われている表記で, あまり一般的に思えないものについては次の一般的な表記を用いる.
リストの場合
型の場合を考える.
catamorphism
"cata-" は catastrophic のそれであって, 下方へ, といった意味らしい. リストについての catamorphism は如何のような関数 である.
ここで は の定数. は なる二項演算子. このような形の は Haskell のような言語では foldr
として知られており
のように書ける. すなわち という関数は によって決定するから, ここでは バナナ括弧 で括ることで
と書くことにする.
例えばリストの長さを取る関数は と書けることが分かる. 他に filter
もこの形で定義できる.
anamorphism
ちょうど catamorphism の逆のもので, unfold
のような名前で知られている関数 を次のように定義する.
ただしここで は なる述語関数 ( は普通の意味で). は なる関数.
やはりこの は で決まる関数なので, 今度はレンズ括弧で括って
と書いて表す.
例えば, 関数 を繰り返し適用する iterate f
という関数 は と書ける.
map 関数
リスト と関数 があるときに, リストの各要素に を適用することで という関数を構成することができる. Haskell では map f
とこれを書くが, 論文に倣って と書くことにする. これは からの catamorphism として書くこともできるし, への anamorphism と書くこともできる.
hylomorphism
リストに関する hylomorphism とは, 例えば木構造をリストにしてやるような「線形再帰関数」のもの. 具体的には
と書き表されるもの. ここで , , であって である.
今度の は によって決定されるので
と書き表すことにする.
そしてこれは明らかに
という合成の形に分解できる. この証明は論文にはあるが省略. リストが一見登場しないが, この合成の形を見れば, 中間でリストを経由してることが分かる.
例えば自然数の階乗を計算する関数 は と書ける. ここで は引数がゼロかを判定する述語とする. つまり であって はそれを乗算しながら畳み込む関数である.
paramorphism
原始再帰のパターンを提供するのが paramorphism であって, リストに関する paramorphism は 次のように定義される.
ここで , である. このような はやはり で決定されるので,
と書くことにする.
の型が豪華になったので, 値を蓄積しながらのような関数が書けるようになった. 例えば tails
は と書ける.
代数的データ型 (Algebraic data types)
双関手 (bifunctor)
双関手とは2つの対象の組を対象に写して2つの射の組を射に写すようなもので, と を とするような といったもの. ただし , となるもの. 双関手の変数として を用いる.
積
2つの対象 の積とは なる対象. は双関手であり, と とに対して を定める.
また任意の に対して 射影関数 と を伴う.
関数的に書くと
また二項演算子 を
と定める. 例えば である. また簡単に を単項コンビネータとして用いて とする. これを用いると と書ける.
和
対象 と の和を, と と加えて との直和として定める.
に対して を定める. これは関数的に書くと, のものは によって に, のものは によって に, そして は に写すもの.
自明な埋め込み射 と が存在する.
積の時と同様に という射に関する二項演算子を導入する. これは選択的に射を適用するようなもので について
のようなもの.
例えば について 後ろに を合成すれば と書ける. そしてやはり単項コンビネータとしても流用して,
のように使う.
矢印
二項演算子 を定める. 対象 について とは対象であって, から への射全体の集まりを表す. そしてこのような対象には次の射が考えられる.
2つの射 と について
を定める.
とはその間を埋める射を受け取って全体を合成して出来る射を返すもの
を と同じ意味で用いる.
関手 があるときに次のような矢印記法を用いる.
また次の合成則がある.
恒等関手, 定数関手
恒等関手 とは対象と射について恒等的に返すもので .
自由に選んだ対象 に対して, 全ての対象を に写すような関手 を定数関手という. ただし射は全て に写すとする.
Lifting
関手 に対して関手 を次のように定める:
また更に双関手 があるときに関手 を次で定める:
Sectioning
二項演算子 があるとき, 関数 を で定める. 同様に関数 を定める. この書き方を sectioning という. 必ず括弧で括る.
以上の記号を用いると, 例えば対象 について なので だと言える.
その他
終対象 (単集合) を と書く. またこれの要素を と書いて void と呼ぶ.
さて述語関数 に対して関数 を次のように定める:
例えば は我々がよく知る if 文 if p then f else g
を表現している.
任意の値を に写す定数関数を と呼ぶことにする. である.
再帰を作るために を定義する.
2つの関手 とがあるとき, 対象 に を与えるような をポリモーフィズム (polymorphism, 多相関数) といい と書く. 自然関手とは可換性を保つポリモーフィズムだと言える. が自然変換であるとはポリモーフィズムであって, 射 があるならば, という可換性を満たすもののこと.
再帰型
以上の操作を再帰的に行って得られる型を再帰型という (ってことだよね).
ここで次のような定理が知られている.
関手 であって連続なものを考えると, ある対象 があって, 次を満たす2つの射 と がある:
に対して上記のような のことを と書いて最小不動点と呼ぶ.
例として関手 を考えると, その最小不動点は であって正にリストとその構成を表している. 同様に の最小不動点は である.
再帰スキーム
一般の再帰型について cata-, ana-, hylo-, paramorphism を与えることをする.
関手 に対して であるとする. 3つのポリモーフィズム
があるとき次を定める.
-
catamorphism
-
anamorphism
-
hylomorphism
-
paramorphism
ここで は任意の対象. また左辺の括弧にはどの関手によって定めるものかを表す添字 があるが, これは誤解がない限り省略する.
1つ目の は を取って の合成を返す関数. これの なので なる が .
2つ目以降について型だけ書くと , , .
リストの場合を思い出すと などと書いてたものは と同等のものであったことが分かる. 同様に と書いていたものは と書き直される. 具体的には次に計算規則として見ていく.
計算規則
cata, ana, para については共通に Evaluation Rule (対訳不明), Uniqueness Property (唯一性?), Fusion Law (融合則) が成り立つことを見ていく. その中で次の幾つかの定理を用いる.
Fixed point fusion (Free theorem)
関数 が正格で, ならば
hylo については ana と cata とに分解できることと次の定理を利用する.
Evaluation Rule for Catamorphism (CataEval)
catamorphism の evaluation rule は次のようなものである:
関手 とポリモーフィズム とその射 について, とすると
これは の定義から従う. であったが の定義より . 両辺の右に を掛けると, は の逆射だったので を得る.
さてこの法則は evaluation rule という名前の通り, を具体的に計算するための方法を示している.
例
リストの foldr
は次のようなものだった
これらに対して が foldr. では具体的な値について foldr の計算をしてみる.
ただし について の場合と の場合に分ける. これは と の場合に分けてるのと同等 ( は同型射なので).
これで全ての場合を網羅できている.
Uniqueness Property for catamorphism (CataUP)
すなわち, 先の Evaluation Rule を満たすような は唯一しか存在しないことを主張する.
これもほぼ自明. は Evaluation Rule のまんまなので自明. . .
Fusion Law for catamorphism (CataFusion)
のとき
どう証明してもいいけど, の定義のを開けば
両辺に左から を掛けて
というわけで は である. 一方で もその である. catamorphism の唯一性 (CataUP) よりそれらは等しく
である.
論文では であることと fixed point fusion を用いて証明できる, と言っている.
リスト畳込み ( foldr
) の融合則
2つのリストの畳込み と について, ある があって,
のとき
包含射は catamorphism
射 に左単位射 ( ) があるとすると, は の逆射になるので である. CataFusion で を代入すれば を得る.
上の図式で の場合を考える. 唯一性より を得る. これらを代入することで,
を得る. これに を代入すると,
一番下の の catamorphism を考えることで
を得る.
catamorphism は正格性を保つ
まず関手 が正格性を保つ, すなわち とする. このとき
が成り立つ. 添字の は の下でのバナナであることを表したのに註意.
. を仮定すると
より従う. ここで最後の式変形には が正格性を保存することと を仮定していることから を用いた.
Evaluation Rule for Anamorphism (AnaEval)
関手 とその について, に対して が定義だったので,
である. この両辺に左から を掛けることで次を得る.
これはやはり に関する評価規則を示している.
例. unfold
のリスト型 について, リストのunfoldは と によって と表されると言った. これの評価を考える.
ここで であるので,
となっていわゆる unfold
を得る.
例. iterate
とリスト型 について とする.
(左からinを掛けることで)
を得る. これは Haskell なのでは iterate f
として知られる.
anamorphism の唯一性 (AnaUP)
anamorphism の融合則 (AnaFusion)
のとき
唯一性より従う.
全射は anamorphism
以上のことは単に catamorphism の双対を取れば導けた. 全く同様に, 包含射即ち左単位射を持つ射が catamorphism であったことから, 全射即ち右単位射を持つ射は anamorphism である.
全射を として, ある によって であるとすると,
が成立する.
これに を代入することで,
を得る.
Splitting Hylomorphism (HyloSplit)
のとき, 合成則 が成り立つ. これによって次の定理が成り立つ.
Shifting Law for Hylomorphism (HyloShift)
関手 があり, , , とする.
上の図式において は に於いても に於いてでも正しく定まり,
が成り立つ.
これは cata や ana と違って陽に が登場しないからこういうことが出来る.
cata と ana の関係
例えば foldr
してから unfold
した結果が元に戻るための十分条件として, ポリモーフィズムのレベルで合成が であることがある.
Evaluation Rule for Paramorphism (ParaEval)
定義がだいぶ前なので, 改めて paramorphism の定義を書くと, について ポリモーフィズム があるとき とは, なる射によって
と書かれるもの.
従って
両辺に右から を掛けることで
を得、これが paramorphism の評価規則になっている.
例. リスト
について の paramorphism を考える.
は なら , さもなくば であって値は であることに註意すると,
唯一性 (ParaUP)
融合則 (ParaFusion)
定理
Parameterized Types (パラメータ化された型)
最初のほうで map 関数というものをやった. 即ち型 に対しては型 というものを定義することが出来, 射 に対して というものを定めることが出来た. また明らかに , が成り立つ. この意味で は関手である . これを一般化する.
Sectioning について (復習???)
双関手 とある対象 について,
であった. つまりこれは関手であって,
と写す.
射 について はポリモーフィズムであって (!!),
Maps
関手 を次のように定義し直す.
ある双関手 と対象 について であると定義する. 同様に対象 については
ある射 があるとき,
が定まる. この catamorphism を であると定義する.
先の "cata と ana の関係" でも見たように,
と書き直すことも出来る.
以上で関手 が定義された. これはリストのマップとして定義した の一般化になっている. とすればリストの場合が導出出来る.
合成
合成に関して次が成立する.
Map-Reduce
関手 と対象 について としたときの を の上の free -type と呼ぶ.
について, であったが, 今 , とすると,
と書き直せる.
射 に対して次で定める を の reduction と呼ぶ:
これに関して次が成り立つ.
さて実は は自然変換である.
このことから の評価規則を得る:
一方で の評価規則は普通に CataEval から次のようになる:
モナド
free type があるとき, モナドを次のようにして与えることが出来る. つまり
について
が成り立つ.