bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

圏論での積と余積―終対象と始対象

今年最後に読む本を定めて、28日に市の図書館から網野義彦著『日本の歴史のよみなおし(全)』と山本淳子著『源氏物語の時代 ― 一条天皇と后たちのものがたり』を借りた。

『日本の歴史のよみなおし』は、中世の時代を中心にいくつかのテーマに沿って横断的に説明している。ロングセラーになっている本なので、読まれた方も多いことと思う。2005年に出版されたこの本は、1991年と1996年に刊行された本の合本である。両方とも、筑摩書房の社員向けに講演した内容をもとに書かれている。このため、要領よくまとまっていて読みやすい。
f:id:bitterharvest:20161231093307j:plain

文字、貨幣、女性などがテーマとして取り上げられている。その中で、「日本の社会は農業社会か」を説明した部分が最も感銘を受けた。1991年の山川出版の高校の教科書には、「封建社会では農業が生産の中心で、農民は自給自足の生活を立てていた」と記述されていたそうである。この根拠になっていたのは、関本直太郎著『近代日本の人口構造』である。この中に、秋田藩の人口構成を示した表があり、そこには、諸士9.8%、百姓76.4%、町人7.5%...と示された表がある。

子供の頃、ご飯を残すと「お百姓さんが丹精込めて作ったものを残してはいけない」と叱られた。百姓イコール農民のイメージを持っていたが、この表を利用した学者も百姓を農民と見なしたようである。

能登半島の時国家の文書を調査していた網野さんは、年貢を納めていない百姓が多いことに気がつく。子供の頃に聞いたことのある言葉だが、いわゆる、水呑百姓である。その頃は、この言葉は貧乏な農家を示していた。しかし、網野さんはそうではないことに気がつく。廻船業などで裕福な生活をしている人たちだ。今でいう兼業農家だ。本業は農業以外の職業だが、所有する農地からの生産高がわずかであるために、水呑百姓として分類された人々だ。

このことを発見した網野さんは、封建社会には農業以外の産業に従事している人が多くいたはずだと主張し、この視点からの研究の必要性を説いている。今春、購入した山川出版の『詳説日本史研究』の261ページには身分別人口構成がある。百姓87.3%となっている。やはり、農業と解釈しているように読める。百姓という言葉は、中国語では一般の人民を指す。網野さんも指摘しているが、かつてはそのような意味で使っていたのではないかと思う。

源氏物語の時代』は、源氏物語が書かれた時代に生きた一条天皇およびその后の定子と彰子の心理状態をあぶりだした本だ。
f:id:bitterharvest:20161231102554j:plain

この時代は摂関政治の最盛期である。一条天皇は、藤原家から政治的な圧力を受けながらも、しなやかに生き抜いていく。定子は中関白家の藤原道隆(みちたか)の娘で才気活発である。彰子は当代一の権力者である藤原道長の娘でおっとりとしたお嬢さんである。

一条天皇は、数え年の7歳で即位し、11歳で結婚する。結婚相手は、いとこの定子14歳である。姉さん女房だが、そういうには二人は若すぎる。姉と弟という関係に近かったのだろう。政略結婚なのだが、一条天皇は定子を熱愛するようになる。定子の兄である伊周(これちか)を含めて、三人は夜を徹して漢詩の知識を競うなど、和やかな生活を享受する。しかし、ヒロインの定子には残酷な悲劇が待ち受けている。伊周が謀反の疑いで配流になり、罪人の家の出としての汚名を背負うこととなる。

一方、天皇の祖父になりたいという欲望を抱く道長は、彰子を12歳で一条天皇の后にする。この時、一条天皇は20歳である。また、二人はいとこである(先ほどの網野さんもいとこ婚だそうだ。そして、なんと彼の両親も、そして義理の両親もいとこ婚だそうだ。少し前の日本では普通だったのだろうか)。

この1年後、定子は24歳で3番目の子供を出産した後、亡くなってしまう。彰子は定子の長男の敦康(あつやす)を、定子が亡くなった1年後に、養子として迎える。この時、彰子は14歳、敦康は2歳であった。継母というには年が若すぎるので、敦康を弟のようにかわいがったのであろう。一条天皇崩御の後、敦康を東宮にするようにと道長に抗議していることからも、このことがうかがえる。政治の世界は、このような情を許さず、彰子が20歳の時に生んだ敦成(あつひら)が東宮になる。

定子が亡くなった後も、一条天皇は定子が忘れられず、悲しい日々を送っていたようだ。しかし、状況を読み、対応が柔軟であった一条天皇は、仲のよい夫婦として彰子と過ごすようになる。敦成(後一条天皇)を、さらには、敦良(あつなが後朱雀天皇)を儲け、後には、聖代と崇められた。

なお、一条天皇は辞世の句を残している。死ぬ間際のか細い声で言ったため、聞き手によってその内容が異なっている。道長の『御堂関白記』には、
   露の身のの宿りに君を置きて 塵を出でぬることをこそ思へ
となっている。また、藤原行成の『権記』には、
   露の身のの宿りに君を置きて 塵を出でぬることぞ悲しき
となっている。

道長は、当然、「君」は娘の彰子だと思っている。従って、この歌は彰子に捧げたものだと解釈している。これに対して、行成は、「君」は天皇が寵愛していた定子だと解釈している(偶然だが、道長と行成は同じ年の同じ日に亡くなっている)。

作者の山本さんは前者だと思っている。物語の筋としては後者の方が面白そうだが、柔軟に対応した一条天皇であれば前者になるのだろうか。

ところで、草枕の著者である清少納言は定子に、源氏物語紫式部は彰子に仕えた。この辺りの心理描写も巧みに描かれているので、楽しく読むことができる本である。

5.圏論での積と余積

歴史の中に普遍性を求めることは大変だ。今日の歴史学は多様性を大切にしているので、さらに大変だ。この究極にある学問が数学である。数学は普遍性を追求する学問だといっても過言ではない。その中でも、圏論は最も抽象的であり、最も一般的な普遍性を求めている。これから圏論の中で論ぜられてきたいろいろな普遍的な性質(universal properties)を説明する。まず、手始めに、積(product)と余積(coproduct)から始める。それでは、その一部を構成する始対象と終対象から説明しよう。

5.1 終対象

終対象の定義から始めよう。これは次のように定義される。終対象とは、対象の一つであるがそれは次の性質を持つ。圏内の任意の対象からこの対象への射が一つそして唯一つだけである。

もう少し、詳しく定義してみよう。
ある圏において、一つの対象を\(A\)とする。また、任意の対象を\(B\)とする。この時、下記の①と②を満たすような\(A\)が存在するとき、\(A\)を終対象という。
①\(f:B \rightarrow A\)なる射が存在する。
②任意の二つの射\(f,g:B \rightarrow A\)が存在するとき、\(f=g\)が成り立つ。

例を示そう。
f:id:bitterharvest:20161231181410p:plain
上図で、\(A\)が終対象である。少し調べてみよう。任意の対象となるのは\(A,B\)の二つである。

対象\(A\)から\(A\)への写像\(id\)のみである。これは①と②の条件を満たしている。

また、対象\(B\)から\(A\)への写像は\(f\)のみである。これも①と②の条件を満たしている。

従って、対象\(A\)は終対象となる。

もう一つの例を示そう。Haskellにはタプルがある。例えば、年齢と性別をタプルで示すと\((age,sex)\)となる。このタプルの構成要素は年齢と性別の2個である。構成要素が\(n\)個のものを\(n\)-tuppleという。\(n\)が1以上のものは分かりやすいと思うが、\(n\)が0の場合はどうであろうか。

上述した源氏物語では、年齢を数え年で考えていた。最近は数え年を使わなくなったので、なじみのない人も多いと思う。数え年は誕生したときに1歳となり、その後は、正月を迎えるごとに1歳ずつ増える。これに対して、満年齢は誕生日を迎えるごとに1歳ずつ増え、最初の1年は0歳である。

0という数は、何もないことを表すので、構成要素がない場合には0-tuppleとなる。これは構成要素がないので()と表される。Haskellでは()はシングルトンと呼ばれる。

シングルトンは特殊な対象である。即ち、いかなるタイプの対象からもシングルトンへの射を用意すると、シングルトンは終対象となる。シングルトンへの射を次のように用意しよう。

unit :: a -> ()
unit _ = ()

実行してみよう。

Prelude Data.Void> :load "unit.hs"
[1 of 1] Compiling Main             ( unit.hs, interpreted )
Ok, modules loaded: Main.
*Main Data.Void> unit 2
()
*Main Data.Void> unit 'a'
()
*Main Data.Void> unit "spring"
()
*Main Data.Void> unit (14,"male")
()
*Main Data.Void> unit ()
()

最初の例は、対象\(Num\)からシングルトンに写像する唯一の射である。即ち、\(unit :: Num -> ()\)である。図で表すと次のようになる。
f:id:bitterharvest:20161231203639p:plain
2番目の例は、対象Charからシングルトンに写像する唯一の射である。即ち、\(unit :: Char -> ()\)である。
3番目の例は、対象[Char]、即ち、文字列からシングルトンに写像する唯一の射である。即ち、\(unit :: [Char] -> ()\)である。
4番目の例は、対象(Num,[Char])からシングルトンに写像する唯一の射である。即ち、\(unit :: (Num,[Char]) -> ()\)である。
5番目の例は少し注意を要する。図で示すように\(id=unit\)である。
f:id:bitterharvest:20161231204059p:plain

上記の例は、\(A\)に写像される対象が自身を除いて一つ(5番目の例では0)であったが、複数ある場合の例を示そう。
f:id:bitterharvest:20161231211106p:plain
上図では、タイプNumとタイプCharの対象を用意した。分かりやすくするために、射をそれぞれの対象ごとに別々に設け、それぞれをunit',unit"とした。

ところで、終対象は一つとは限らない。複数の場合もある。しかし、この場合でも、それぞれを構成する射の間が同型写像となる(これについては後の記事で説明する)。その結果、これらの終対象を同じものとみなすことができる。

5.2 始対象

始対象次のように定義される。始対象とは、対象の一つであるがそれは次の性質を持つ。この対象から圏内の任意の対象への射が一つそして唯一つだけである。

もう少し、詳しく定義してみよう。
ある圏において、一つの対象を\(A\)とする。また、任意の対象を\(B\)とする。この時、下記の①と②を満たすような\(A\)が存在するとき、\(A\)を始対象という。
①\(f:A \rightarrow B\)なる射が存在する。
②任意の二つの射\(f,g:A \rightarrow B\)が存在するとき、\(f=g\)が成り立つ。

例を示そう。Haskellでは、以前のブログで説明したが、Voidというタイプを用意している。

*Main Data.Void> :i absurd
absurd :: Void -> a 	-- Defined in ‘Data.Void’

これを図で示すと次のようになる。
f:id:bitterharvest:20161231213029p:plain

Voidという用語はC++でも使っているので、混乱を起こす。C++でのvoidは、先ほど説明したスケルトン()と同じである。

先ほどの説明で()は何もないということを表していた。HaskellでのVoidは、空っぽと説明されることが多いが、これでは、()との違いが分からない。適当な日本語がないので、英語を用いるが、HaskellのVoidはPrinciple of explosionである(explosionは爆発を意味する)。即ち、「命題A=>Bの前提条件Aが偽である時、A=>Bは真である」という論理での偽の部分に当たるのが、Voidである。Voidを偽とみなせば、命題absurd :: Void -> aは真であることになる。即ち、前提条件が偽であれば、どのような命題を持ってきたも真となる。言い換えると、矛盾からは何事も引き出せるということになる。とても、比喩的に述べると、ビッグバンが起きるようなものだ。超高温、超高密度な火の塊から宇宙が誕生するような感じだ。

面倒くさい議論になったが、哲学的な説明から離れて、分かりやすい例を示そう。0で始まる自然数を昇順(<)に並べると次のようになる。
f:id:bitterharvest:20161231215356p:plain
昇順で用いた大小関係(<)を射とみなし、対象\(A\)と\(B\)を次のように定めると\(A\)は始対象となる。
f:id:bitterharvest:20161231220346p:plain

先ほどと同じで、始対象についても、複数存在する場合があるが、その場合には、これらは等価であるとみなせる。

ところで上の図で、降順(<)に並べ、射の矢印を逆方向にすると、0は終対象となる。このような性質を双対(Duality)という。
f:id:bitterharvest:20170101095446p:plain

圏には始対象あるいは終対象が存在しない場合がある。圏を構成したときは、どれが始対象になるのか、どれが終対象になるのか、あるいは、なぜ存在しないのかを考えると、圏に対する認識が深まることと思う。

モナドを音楽の力を借りてアナログ的に説明する

4.8 モナドを関手(ファンクタ)を用いずに説明する

数学の本を読んでいると、1ページを読むのに数時間もかかることが往々にして起きる。特に、定理があってその証明が書かれているときがそうだ。純粋な数学的用語で書かれているときは、その背後にある概念を把握するまでにかなりの時間を取られ、読んでいるという感じではない。まるで、暗号を解読しているような状況に追い込まれてしまう。

最近は、日本の古代史や中世史の書籍を読む機会が多くなり、同じような経験をすることがある。研究論文に近い文章を読んでいるときは、それぞれの用語にある背景を吟味する必要があるため、一行の文章を理解するのに、長い時間を必要とする時がある。このような時は、前に何が書かれていたのかを忘れてしまい、同じページを行ったり来たりしながら読むことになる。

中世史の若手研究者の呉座勇一さんが書かれた書籍は、内容は高度だが、分かりやすい言葉で書かれていて、とても読みやすい。何冊か既に読んだが、『一揆の原理』の中に、面白い例があったので、紹介しよう。
f:id:bitterharvest:20161223112336j:plain
室町時代が始まった頃、朝廷は北朝南朝とに分かれていた。南北朝時代と呼ばれる。この時代が終わるころ、日本史研究者の間では「中世後期」と呼ばれる時代になると、一揆が社会全体に広がる。一揆にはいくつかのタイプがあり、その中に徳政一揆がある。簡単に言うと借金をチャラにしてくれというものだ。この時代になぜこのような一揆が生じるようになったかを解明するのが、歴史学者の役割である。

古い戦後歴史学では「悪徳高利貸に苦しめられた民衆の怒りが爆発し、徳政一揆をおこした」と考えられていたそうである。説明の内容は省くが、この記述の部分を論文調で書くと「貨幣経済の農村への浸透を契機とした都市高利貸資本の農村浸食」となるそうだ。相当に専門的な知識を有していないと理解するのに時間を要する。

圏論にも似たような点が多い。専門的な知識を有している仲間たちの間では、専門用語を多用して説明すれば、簡潔に述べることができるだろうが、あまり、知識を有しない人に同じように理解してもらうためには、平易な言葉で、比喩を多用しながら、逃げられないように説明する必要がある。

Milewskiが関手という専門用語を用いないでモナド(monad)の説明をしていた。これをヒントにして、同じように、関手を使わずに、モナドの説明を試みよう。数学とはだいぶ距離があるように思えるが、音楽の世界を利用する。小学校での音楽の時間に出会った曲に「朝はどこから」という歌があった。その中で、1番の歌詞の終わりの方に「おはよう」という部分がある。そこだけ楽譜に落とすと、次のようになる(原曲の楽譜とは異なっている)。
f:id:bitterharvest:20161225215157p:plain
少し単調なので、クラシック風にアレンジする。
f:id:bitterharvest:20161225222727p:plain

原曲からアレンジした曲へ矢印を引き、矢印に\(classic\)という名前を付けてみよう。
f:id:bitterharvest:20161226100237p:plain

なんとなく、圏に見えないだろうか。自分から自分への写像\(id\)をつけてみよう。図のように立派に圏になっていることが分かる。
f:id:bitterharvest:20161226100504p:plain

それでは、この楽譜を演奏したらどうなるだろう。
f:id:bitterharvest:20161226100718p:plain

上の図で、スピーカーのところを押したら曲が流れてくるとよいのだが、はてなブログでは、残念ながら、音楽をアップロードできない。仕方がないので、ブログDraw the Dotsを利用して聞いてほしい(その他にも、Music Editor - abcjs, abc Converter - MandolinTab.netなどがある)。

Draw the Dotsが開いたところで、長方形の枠の中に、ABC記法に従って楽譜を記入すると、下の方に五線譜での楽譜が表示される。また、midiファイルも用意されているので、これをダウンロードして視聴する。原曲の部分はABC記法では次のようになる。

X: 1
T: Original
Q: 1/4=100
M: 4/4
K: C
E2EFG4-|G6z2|
w: お は * よ ―

上記の楽譜を書き込んだブログDraw the Dotsの画面を下図に示す。
f:id:bitterharvest:20161226105506p:plain
画面右端の真ん中あたりにdownload midiがあるので、ここより、midiファイルを獲得し、視聴できる。
また、クラシック風にアレンジした曲は、ABC記法では以下のようになる。

X: 1
T: Classic
Q: 1/4=100
M: 4/4
K: G
B2 B1/2A1/2B1/2c1/2 dd1/2e1/2 d1/2c1/2B1/2c1/2|d6z2|
w: お は * * * よ * * ― * * * ―

聞き比べての印象はどうであろうか。うまくアレンジされているだろうか。midiで演奏された原曲とクラシック風の曲にも、楽譜の時と同じように、矢印を引くことができる(矢印に名前を付けるのはしばらく保留しておこう)。
f:id:bitterharvest:20161226110705p:plain

これもやはり恒等射を付加することで、立派な圏を得ることができる(二つの間の曲の射は実態が明らかになるまで?で示す)。
f:id:bitterharvest:20161226110839p:plain

さて、これまでに得た二つの圏を並べてみよう。
f:id:bitterharvest:20161226111255p:plain

ここで質問したい。楽譜で書かれた曲(赤い色の\(A\))とmidiで演奏された曲(緑色の\(A\))は、同じものだろうか。同じだという人もいるだろうし、違うという人もいるであろう。著作権をもとに考えれば同じだろう。物理的に考えると異なっているだろう。ある時は同じであるとみるし、別の時は異なるとみるのがモナドだ。そのため、惑わされてしまう。しかし、ここでは、この二つは同じものと考えておこう。

それでは、midiで演奏された二つの曲を結ぶ矢印は、楽譜で書かれた二つの曲の矢印と同じであろうか。後者の方の矢印は、ある規則に従っているのであれば、それはプログラムで表すことが可能である。このプログラムを用いて、一方のmidiの曲から他方のそれを作り出すことができるであろうか。これはどうも難しそうだ。

それでは、midi間での射を決めよう。そこで、次の図のように、楽譜の\(A\)から、midiの\(B\)を作り出す関数を考える。
f:id:bitterharvest:20161226113215p:plain
この関数は、先ほどのプログラムを実行した後にmidiに変換すればよいので、関数として定めることができる。この関数を\(classic?\)とする。midiでの二つの曲をつなぐ関数を今定義した関数\(classic?\)を用いることにする。
f:id:bitterharvest:20161226113802p:plain

この関数がモナドの神髄である。しかし、図を見る限り、midiの方の圏(対象が緑色で示されている)からは、赤色の\(A\)を発見することができない。なぜ、赤色の\(A\)を用いることができるのかと悩んでしまう。ここで、先ほどの赤色の\(A\)と緑色の\(A\)は同じというおまじないを使う。緑色の\(A\)があるのだから、緑色を剥げば、赤色の\(A\)が得られるだろうと考える。そこで、これを利用して、関数を適応する。Haskellでの型シグネチャを用いると次のように表すことができる。

classic? :: m a -> (a -> m b) -> m b

なお、上記の\(a\)は赤色の\(A\)であり、\(m \ a\), \(m \ b\)は緑色の\(A,B\)である(以下同じである)。

midiの曲の方を圏にするためには、自分から自分への射を必要とする。これも、少し、特殊である。楽譜からmidiで演奏するときの写像を考えよう。これを\(m\)と表すことにしよう。これを用いると次の図を得る。
f:id:bitterharvest:20161226115803p:plain

ここで得た関数\(m\)が、midiで演奏される曲の\(id\)となる。
f:id:bitterharvest:20161226124047p:plain

これは、楽譜(赤色の\(A\))とmidiによる演奏(緑色の\(B\))への写像\(classic?\)がmidiによる演奏間での射となったのと同じ理由である。Haskellの型シグネチャを用いると次のようになる。

idA :: m a -> (a -> m a) -> m a
idB :: m b -> (b -> m b) -> m b

圏論では射の合成も重要な役割をなす。そこで、クラシック風の曲をワルツ風の曲にアレンジしてみよう。
f:id:bitterharvest:20161226123246p:plain

ABC記法では以下のようになる。

X: 1
T: Classic
Q: 1/4=100
M: 4/4
K: G
B2 B1/2A1/2B1/2c1/2 dd1/2e1/2 d1/2c1/2B1/2c1/2|d6z2|
w: お は * * * よ * * ― * * * ―

アレンジした曲の関係は次の図のようになる。
f:id:bitterharvest:20161226124810p:plain

midiで演奏された曲の間では、原曲\(A\)からワルツ風の曲\(C\)への射\(compose?\)は、原曲\(A\)からワルツ風の曲\(B\)への射\(classic?\)とワルツ風の曲\(B\)からワルツ風の曲\(C\)への射\(waltz?\)との合成となる。即ち、\(compose?=waltz? \circ classic?\)となる。

Haskellの型シグネチャで表すと

classic? :: m a -> (a -> m b) -> m b
waltz? :: m b -> (b -> m c) -> m c
compose? :: m a -> ((a -> m b) -> m b -> (b -> m c)) -> m c

となる。\(compose?\)の関数\( ( (a \rightarrow m \ b) -> m \ b -> (b \rightarrow m \ c) )\)が二つの関数\( (a \rightarrow m \ b)\)と\( (b \rightarrow m \ c)\)との合成になっていることに注意してほしい。

ここまで、音楽を例にとって説明したが、説明した内容は汎用的である。このため、モナドを形成しているほかの世界にも応用することができる。例えば、カッコが使える世界を考えてみよう。
f:id:bitterharvest:20161226130355p:plain

カッコの世界では、\(A\)も\((A)\)同じである。これは、楽譜での曲\(A\)とmidiで演奏された曲\(A\)を同じと見做したのと同じ理屈である。\(f,f?\)のHaskellでの型シグネチャを求めると次のようになる。

f :: a -> b
f? :: m a -> (a -> m b) - m b

\((a)\)に\(f?\)を施すことを考えよう。\((a)\)は\(m \ A\)である。また、\(a\)は\(A\)である。そこで、\(aに(a \rightarrow m \ b)\)を施すと、\(m \ b\)を得る。従って、カッコの中の\(a\)が変わるので、\(f?\)を施すと\(( (b) )\)となる。外側のカッコはもともとあったもので、内側のカッコは今回の変換で得たものである。\((b)\)は\(b\)と同じなので、\(( (b) )\)は\((b)\)と同じである。即ち、カッコが付いたこの世界では、たくさんのカッコが付くことになるが、この世界ではあってもなくても同じである。

前に書いたクライスリ圏でも同じことが言えるが、これについては、確認して欲しい。

ブライン液につけて、ジューシーなターキーを食卓に

今年もまた、ターキーを焼く季節がやってきた。孫や子供たちの都合によって、作る日は異なる。今年は、23日がよいということなので、クリスマスイブのさらにイブに食することとなった。

ターキーの焼き方は、イギリス滞在経験の長い隣の家から教えて頂いた。もう、25年以上も前のことになる。その間に焼く技術も進化した。特に、鶏肉をジューシーに焼く方法が、この春、NHKあさイチで紹介された。この番組では、これまであまり人気のなかった鳥の胸肉を美味しく調理する方法として、ブライン(Brine)液に浸すとよいと提案された(この液を用いると、浸透圧で水が肉に吸収される)。胸肉は、あのぱさぱさ感が障害となっていたようである。しかし、ブライン液を利用するようになってから、ジューシーな食感が出せるようになり、低カロリー高タンパクであることとも相まって、胸肉の人気が高まったそうである。

今年は、ブライン液を利用して、ジューシーなターキーを試みた。

ターキーは、例によって、明治屋で仕入れた。あまり大きなターキーは、日本製のオーブンレンジでは焼けないので、3Kg前後のものを手に入れた。
f:id:bitterharvest:20161223205816j:plain

仕入れたのは10日前だったので、4日前までは冷凍庫に、そのあとは冷蔵庫に移して保管した。昨日(1日前)、解凍状況を調べたら、まだ、凍っている部分があったので、日中台所に放置しておき、夕方、冷蔵庫に戻した。

今日(23日)、朝食を済ませた後、ブライン液を作成した。ブライン液は、100ccの水に対して5gの塩ということなので、3リットルの水に150gの塩を溶かして作った(NHKでは、塩と等量の砂糖も加えていたが、甘くなることには迷いがあったので避けた)。丈夫なビニールの袋を2重にしてその中にターキーを入れ、さらに、ブライン液を全部加え、ターキーの全表面にブライン液が浸るようにビニール袋を絞った。さらに、これを、氷の入ったもう一つのビニール袋の中に入れて、低温に保って、廊下に放置した(冷蔵庫にと書いてあったが、相当な重量になっていたので、冷蔵庫の棚が壊れるのを避ける処置である)。
f:id:bitterharvest:20161223210949j:plain

ブライン液に浸してから4時間後にターキーを取り出した。ビニール袋から少し水がこぼれたので、正確ではないのだが、残った水の量は2.4Kgであった。おそらく、(全体の水の量は塩も含めて3.15Kgなので)500-600g程度の水が肉に吸収されたのではないかと思う。随分と大量の水が吸収されたことになる。ターキーに触ってみると、瑞々しい。美味しく焼けそうな気がする。

さて、ターキーの前処理が済んだので、後は、これまでの手順でターキーを焼いた(詳しい手順はここを参照)。
サラダに使った後の不要な部分や、冷蔵庫の中に残っている野菜の残り、即ち、キャベツの芯、ニンジンの皮、細切りにした玉ねぎ、セロリの茎、ブロッコリの芯、レモンバームローズマリーなどを下にひき、ターキーに胡椒を塗りこみ、さらには、バターを張り付けて、焼くための準備をした(この料理を教わった時は、塩も揉みこむこととなっていたが、ブライン液に浸したので、今回はやめた)。なお、お腹の中に首の部分が入っていたので、これは後日のスープのだしで使うことにし、冷蔵庫にしまった。
f:id:bitterharvest:20161223212824j:plain
昨年の記事で説明したが、最近のターキーにはポップアップタイマーが付いている。ターキーが焼きあがった時に、赤いマークの棒が飛び出す。中の肉汁の色を調べながら、焼き具合を見る従来の原始的な方法よりは、簡単で、便利で、ハイテクでもある。

最初の10分は250度で、その後は180度で焼いた。時々、出汁をかけること(ベイスティングbasting)は必要ないというレシピもあったが、これまでの習慣が抜け切れず、時間を少し延ばして20分に一回は出汁をかけた。焼く時間は150分となっていたが、2時間程で、ポップアップタイマーの赤い棒が飛び出してきたので、火を落とし、そのまま、オーブンの中で蒸らした。出来上がりは次のようだ。
f:id:bitterharvest:20161223213942j:plain
サラダやスープを添えて、成長盛りの孫たちと一緒に美味しくいただいた。ブライン液を利用した効果は絶大で、胸肉もジューシーでとても美味しかった。食卓を賑やかにしてくれた料理の仲間たちに、最後に登場してもらおう(コーンスープは恥ずかしがり屋なので、抜けている)。
f:id:bitterharvest:20161223214906j:plain
f:id:bitterharvest:20161223214944j:plain
アンコールを頂き、来年の出場も決まった。

ドイツ料理「リンダールーラーデン」を楽しむ

クリスマスが近づくとシュトレン(Stollen)を見かけるようになる。ドイツの菓子パンだが、伝統的にクリスマスの時期に食されている。先日、Kaldiで大量に販売していた。季節ものなので購入したが、少し、甘すぎるかなと感じた。

そうこうするうちに、ドイツ料理には何があるのだろうと考え始めた。市ヶ谷には、パウケというドイツ料理のレストランがある。何回か訪れたことがあるが、本格的な料理を食べた記憶がない。いつも、ビールを飲むことが目的で、ソーセージをおつまみに食べたことしか覚えていない。

インターネットで調べると、グラーシュが出てくる。この料理、以前に記事で紹介した。ドイツのレストランでよく見かける料理ではあるが、ハンガリー起源の料理だ。

さらに検索していくと、ドイツに在住しているご婦人のブログに行きついた。リンダールーラーデン(Rinderrouladen)と呼ばれるドイツの家庭料理を紹介していた。ご主人がドイツ人なので、伝統的な料理なのだろうと思い、少し調べてみた。

ドイツ語で書かれたレシピはたくさんあったが、大体の内容はつかめるものの、正確には読むことができない(大学生の頃には簡単な小説は読めるようになったのに、その後、使う機会がなかったので、すっかり忘れてしまった)。仕方なく、英語のレシピをいくつかさっと読んでみた。

家庭料理ということもあるのだろう。いろいろなレシピがあったが、それらに共通しているのは、薄く切った牛肉に野菜を巻いて長い時間かけて煮込むということであった。

正統な作り方はないようなので、読んだレシピを参考にしながら、リンダールーラーデンなるものを作ってみた。ちなみに、Rinderは「牛肉」を、Rouladenは「巻いた料理」を意味するそうだ。

今日の食材に登場してもらおう。
f:id:bitterharvest:20161222201853j:plain

次に下ごしらえをしよう。玉ねぎ(2個)は、牛肉の中に入れるだけでなく、煮込むためのスープにも用いるので、薄く切る。
f:id:bitterharvest:20161222202110j:plain
さらに、肉に包む分はもう少し小さく切る(1/3程度を細かく。残った場合には煮込み用のスープに入れるので多くても気にしない)。
f:id:bitterharvest:20161222202229j:plain
ピクルス(4本)を細長く切る。
f:id:bitterharvest:20161222202440j:plain
牛肉(350g程度)を広げる。ドイツではリンダールーラーデン用に牛肉を切ってくれるそうだが、日本ではかなわないので、今回は、すき焼き用の肉を購入した。ドイツ料理なので、赤身の方がよいだろうと思い、米国産にした。
f:id:bitterharvest:20161222202803j:plain
さらに、ベーコンを広げた牛肉の上に重ね、マスタードを塗る。
f:id:bitterharvest:20161222202858j:plain
隅の方に、ピクルスと玉ねぎを重ねる。
f:id:bitterharvest:20161222203142j:plain
この上に、塩、コショウ、パプリカをまぶす。
f:id:bitterharvest:20161222203242j:plain
野菜がのっている方から、牛肉を巻く。
f:id:bitterharvest:20161222203338j:plain
料理用のタコ糸で牛肉巻を縛る。
f:id:bitterharvest:20161222203442j:plain
フライパンにバターをひき、牛肉の表面が茶色になる程度まで焼く。
f:id:bitterharvest:20161222203608j:plain
f:id:bitterharvest:20161222203659j:plain
鍋に、残った玉ねぎ、ピクルス、表面を焦がした牛肉をいれ、さらに、赤ワイン(150cc程度)、細かく切ったニンニク(1かけ)、トマトペースト(大匙1杯)、マギーブイヨン(1個)を加える。中火で90分間煮込む。水分が少なくなってきたら、水を少しだけ加える。
f:id:bitterharvest:20161222204049j:plain
リンダールーラーデン(牛肉巻)を取り出す。
f:id:bitterharvest:20161222204604j:plain
鍋に残されたスープを取り出し、煮詰める。
リンダールーラーデンのタコ糸を外し、皿に盛り付け、煮詰めたソースをかけ、食卓に出す。今回は、温野菜とともに食べた。
f:id:bitterharvest:20161222205000j:plain
リンダールーラーデンを真ん中で切断すると、中の野菜が見えてきれいである。
f:id:bitterharvest:20161222205159j:plain
リンダールーラーデンは赤ワインとの相性がよく、おいしくいただいた。ただ、家庭料理にしては、味が強すぎるようにも感じた。マギーブイヨンを入れなくてもよかったような気がした。

称名寺(金沢文庫)を訪れる

称名寺を訪ねた。森茂暁著『闇の歴史、後南朝』を読んだのがきっかけになった。

f:id:bitterharvest:20161216140752j:plain

室町時代の幕開け(1336年)とともに始まった南北朝時代は、1392年に北朝南朝を吸収して合体することで終了する。その後の歴史は合体を主導した側(北朝)を中心に描かれた。そして、この本が出版されるまでは、南朝のその後について、総括的に記述されることはなかった。合体によって南朝は滅びたと思われがちだが、実はそうではない。そのあと(1479年までの)90年間もの間、室町幕府に反対する勢力のシンボルとなって、幕府の前に立ちはだかっている。このような状況をこの本は詳述している。

この本のなかで、永享(えいきょう)の乱(1438年)についても説明がある。この乱では、将軍権力の拡充を目指す第8代将軍足利義教(よしのり)と将軍職を奪おうとする鎌倉公方足利持氏(もちうじ)が対決した。たいした戦いもなしに、将軍家が勝利する。持氏は称名寺で出家し、その後、永安寺に移され、関東管領上杉憲実(のりざね)を介して義教に赦免を願うが、許されるわけもなく、逆に憲実に攻められ、自害する。

この本で、称名寺が出てくるのはここだけだ。なぜ、1回だけなのに注目したのだろうか。それは、先週の土曜日に横浜歴史博物館で称名寺の古文書を見たことによる。

横浜市あるいはその近辺で義務教育を受けた人は、金沢文庫について学校で説明を受けたことがあると思う。金沢文庫は、鎌倉時代の中期に北条実時(さねとき)が武家の文庫として設置したものである(北条実時は、第2代執権北条義時の孫で、金沢流北条氏の実質初代で金沢実時ともいわれる。これから金沢文庫と呼ばれる)。現在は、神奈川県立金沢文庫になっていて、称名寺所有の資料を保管展示している。今年、これらの資料が国宝となった。

これを記念して、国宝となった称名寺の古文書が横浜市歴史博物館や金沢文庫などで展示されている。先週の土曜日に横浜市歴史博物館で用事があり、そのついでに、称名寺の資料を見学した。
f:id:bitterharvest:20161216194846j:plain
今日(12月16日)は、その続きではないが、称名寺金沢文庫を訪れた。金沢文庫は撮影禁止であったので、称名寺だけ紹介しよう。

称名寺で最も大きな建物は山門(1818年建立)である。
f:id:bitterharvest:20161216181035j:plain

山門の手前には、塔頭(たっちゅう)光明院表門があった。1665年の建立で、三渓園に移設された建物を別にすれば、造営年代が判明する横浜市内の建物の中では最も古いそうである。f:id:bitterharvest:20161216181504j:plain
境内の中に入ると、阿字ヶ池がある。
f:id:bitterharvest:20161216181705j:plain
そこには二つの橋がある。
山門よりの橋は、反り橋になっている。
f:id:bitterharvest:20161216181854j:plain
もう一つの橋は平らである。
f:id:bitterharvest:20161216181933j:plain
平らな橋の先には、金堂(1681年建立)がある。
f:id:bitterharvest:20161216182110j:plain
その右側には、釈迦堂(1862年建立)がある。
f:id:bitterharvest:20161216182227j:plain

金沢文庫へはトンネルを抜けるとたどり着く。
f:id:bitterharvest:20161216184840j:plain

称名寺の宗派は真言律宗である。真言宗の開祖は空海(弘法大師)。平安時代始まりの桓武天皇の時世に、最澄(天台宗の開祖)とともに遣唐使で唐にわたった僧だ。真言律宗の開祖はだれなのだろう(ちなみに、律宗の開祖は奈良時代帰化鑑真である)。ウィキペディアで調べてみた。西大寺の興正菩薩叡尊(えいぞん)が中興の祖となっている。

金沢文庫の写真には、忍性菩薩の展示会への案内がある。忍性(にんしょう)は、第5代執権北条時頼の病気平癒のために、金沢文庫創設者である北条実時によって鎌倉に招かれた。時頼の病気回復に成功したのをきっかけに、忍性の師である叡尊を鎌倉に招くこととなった。そのため、実時は、宋版一切経の7,000帖にも及ぶお経全巻を2セット輸入し、1セットを叡尊西大寺に、もう1セットを称名寺に贈った。

叡尊にあった実時は、叡尊と志を同じにする僧を称名寺に招聘したいと思うようになり、忍性に相談したところ、審海(しんかい)が紹介された。

また、忍性は鎌倉の極楽寺の開山となった。彼は87歳で亡くなったが、多大な功績により「忍性菩薩」と呼ばれることとなった。来年2017年は、忍性生誕800年を迎える。忍性は、貧者や病人の救済に身を尽くしたそうである。特に、ハンセン氏病患者を毎日背負って町に通ったそうである。社会福祉の祖とも言われる。

称名寺は有名なお寺ではあるが、観光客は多くない。今日の見学者は10人前後。散歩に出てきたのであろう、老夫婦が目立った。厳しい寒さの日であったが、快晴だったので、静かなたたずまいを楽しむことができた。また、和泉元彌主演の映画『忍性』の上演も始まったようなので、鑑賞してさらに理解を深めたいと思っている。
f:id:bitterharvest:20161217091957j:plain

国宝・円覚寺舎利殿を初冬に訪れる

何回となく訪れたことがある円覚寺だが、舎利殿だけはいつも遠目に見るだけで、訪れたことがない。今回(12月10日)、運よく、舎利殿を訪れるイベントがあり、それに参加した。

円覚寺は、鎌倉時代の1282年に建立された。モンゴル帝国(元)が日本を攻めてきた元寇、即ち、文永の役(1274年)と弘安の役(1281年)で戦死した両国の武士たちの魂を鎮めるために、第八代執権北条時宗が創建した寺である(モンゴル兵士の鎮魂をも願った時宗の優しい人柄がしのばれる。この他にも国家の鎮護と禅の普及という目的が創建にはあった)。

鎌倉時代の日本の人口は500万人。モンゴルが二回目に攻めてきた弘安の役では、元・高麗軍を主力とした東路軍が約40,000~56,989人、旧南宋軍を主力とした江南軍が約100,000人であったとされている(兵士数はウィキペディアによるが、なぜ、端数があるのだろう。それもとても細かな)。当時の日本の人口の3%にも及ぶ軍隊が押し寄せてきたことになる。現在の人口で換算すると、その数は300万人にも及ぶことになる。想像を超える国難であったが、いわゆる神風、台風が来襲したために、この難を逃れた。

このことによって、我々が学んだ教科書では、時宗はモンゴルの侵略を阻止した英雄として高く評価されていた。しかし、中世の時代の見直しが進むにしたがって、時宗についても評価が分かれている。

元寇が始まる前の1268年には、大蒙古國皇帝奉書をモンゴル皇帝から受け取っている。その内容は次のようになっている。

天の慈しみを受ける大蒙古国皇帝は書を日本国王に奉ず。朕(クビライ・カアン)が思うに、いにしえより小国の君主は国境が相接していれば、通信し親睦を修めるよう努めるものである。まして我が祖宗(チンギス・カン)は明らかな天命を受け、区夏(天下)を悉く領有し、遠方の異国にして我が威を畏れ、徳に懐く者はその数を知らぬ程である。朕が即位した当初、高麗の罪無き民が鋒鏑(戦争)に疲れたので命を発し出兵を止めさせ、高麗の領土を還し老人や子供をその地に帰らせた。高麗の君臣は感謝し敬い来朝した。義は君臣なりというがその歓びは父子のようである。
この事は王(日本国王)の君臣も知っていることだろう。高麗は朕の東藩である。日本は高麗にごく近い。また開国以来時には中国と通交している。だが朕の代に至っていまだ一度も誼みを通じようという使者がない。思うに、王国(日本)はこの事をいまだよく知らないのではないか。ゆえに特使を遣わして国書を持参させ朕の志を布告させる。願わくは、これ以降、通交を通して誼みを結びもって互いに親睦を深めたい。聖人(皇帝)は四海(天下)をもって家となすものである。互いに誼みを通じないというのは一家の理と言えるだろうか。
兵を用いることは誰が好もうか。王は、其の点を考慮されよ。不宣。
至元三年八月 日

古続記(吉田経長の日記)によれば、この国書を受け取った時、朝廷は返書を送ることを提案したが、幕府は黙殺せよと判断したそうである。どちらをとればよかったのかは、この書の読み方によって異なる。

判断の前提に、中国の手紙での「不宣」は対等な関係にあるときに使う結びである、ということを利用できる。これを念頭において、「兵を用いることは誰が好もうか」を解釈すると、圧倒的な兵力で日本を制圧するよりも、穏やかに和平したいと望んでいたのではないかと読める。

さらに、モンゴル皇帝の使者である趙良弼(ちょうりょうひつ)は、1272年に、モンゴル皇帝のクビライに、日本は「占領に値しない」と伝えていた。そのため、クビライは積極的に攻めようと思ってはいなかったのではないかと考えるのが妥当なように思える。

時宗は、漢文で書かれた国書を理解することができず、南宋から来た禅僧の意見を求めたのではないかと予想される。モンゴル帝国に敗れて日本に亡命してきた彼らは、モンゴル帝国と対決するように文章を捻じ曲げて意見を述べたのではないかと想像される。

このような理由から、もし返書を出していれば元寇はなかったのでと考えている学者もいる。

さらに、時宗は、自から戦場に赴こうとすることもなく、また、北条家の名だたる武士を九州に送ることもなく、九州在郷の少弐氏(しょうにし)を大将にするなどして、他人事のように、モンゴルの襲来をかわそうとしている。これは国の命運を握る職にあるものの施策とは思えないということで、時宗の統治者としての能力を疑っている学者もいる。

このように評価の分かれている時宗だが、元寇での犠牲者が多大であったのには、よほどショックだったのであろう。両国の戦死者を鎮魂するために円覚寺を創建した。

円覚寺の開山となったのが無学祖元(むがくそげん)である。彼は、南宋(現在の中国浙江省寧波市)出身の臨済宗の僧である。南宋がモンゴル軍の侵入を受けた後の1279年に、時宗の招きに応じて来日した。彼よりも前に南宋から渡来していた禅僧の蘭溪道隆(らんけいどうりゅう)の死後、彼を引きついで建長寺の住持となり、その後、円覚寺を開山した。

円覚寺にまつわる説明が長くなったが、さて、昨日のイベントの道順に従って、円覚寺を訪れてみよう。

円覚寺は、何度も火災にあっているそうで鎌倉時代からの建物は残っていないそうである。関東大震災(1923年)でも壊滅的な被害を受けたそうで、その時に被害を受けなかった建物はたった二つとのこと(何とも恐ろしい)。そのうちの一つが、三門(山門)である(他の一つは舎利殿がある正続院内の一つの建物)。この門は三つの解脱、空・無相・無願を象徴しているといわれている。江戸時代(1785年)の建物だそうだ。この門を通るときは、「門を通らずに門を通る」ことと、案内をしてくれた副住職の方が仰った。なお、この門は夏目漱石の『門』という小説の舞台になった。『門』の書き出しは次のようになっている。

宗助は先刻から縁側へ坐蒲団を持ち出して、日当りの好さそうな所へ気楽に胡坐をかいて見たが、やがて手に持っている雑誌を放り出すと共に、ごろりと横になった。秋日和と名のつくほどの上天気なので、往来を行く人の下駄の響が、静かな町だけに、朗らかに聞えて来る。肱枕をして軒から上を見上げると、奇麗な空が一面に蒼く澄んでいる。その空が自分の寝ている縁側の、窮屈な寸法に較べて見ると、非常に広大である。

三門の写真は、
f:id:bitterharvest:20161211062757j:plain
f:id:bitterharvest:20161211062906j:plain
また、紅葉も綺麗であった。
f:id:bitterharvest:20161211063001j:plain
副住職の方によれば、今年は11月の初めに寒い時があり、その月の終わりに温かくなったので、早く紅葉になった木と、遅くそのようになった木があるそうで、12月のこの時期に紅葉を楽しめることはあまりないことだそうだ。

次に訪れたのが仏殿である。仏殿は関東大震災で倒壊し1964年に再建された。鉄筋コンクリート造りの建物である。殿内には、円覚寺の本尊である宝冠釈迦如来坐像が安置されている(通常、釈迦如来は頭には何もつけていないが、円覚寺の釈迦如来は宝冠をかぶっているのが特徴である)。
f:id:bitterharvest:20161211080241j:plain

また、天井には前田青邨の監修で日本画家守屋多々志が描いた天井画の「白龍図」がある。
f:id:bitterharvest:20161211064802j:plain

次に説明を受けたのは、選仏場である。ここは僧のための座禅道場である。
f:id:bitterharvest:20161211065413j:plain

この右隣には、居士林があり、一般の人を対象に座禅が行われていた。この日、案内してくれた副住職の方も、民間企業に勤めているときに、この禅道場に通ったそうである。何か思うところがあったのだろう、企業をやめて、修行僧になり、今日に至ったとのこと、彼にとっては今のきっかけとなった場所であると感慨深げに話をしてくれた。

舎利殿に向かう道すがら妙香池を見る。岩が虎の頭に見えるそうだ。その気になれば何となくだが、
f:id:bitterharvest:20161211070333j:plain

さて、今日の目的である舎利殿に入る。舎利殿は神奈川県唯一の国宝建造物である。
f:id:bitterharvest:20161211070733j:plain

舎利殿は、入母屋造で、柿(こけら)葺である(屋根の下部が寄棟造、上部が切妻造のものを入母屋造という)。舎利殿は最初から円覚寺にあったものではないそうだ。尼寺の太平寺の仏殿を移築したもので、室町時代の建物と推察されている。1556年に安房の国の里見義弘が鎌倉を攻めたときに、太平寺も攻撃を受けた。青岳尼と本造聖観音菩薩立像が奪われ、青岳尼は、その後、里見義弘の正室となった。太平寺は廃寺となり、仏殿が円覚寺に移築されたそうだ。

なお、舎利殿関東大震災で倒壊したが、その写真が文化庁のホームページに掲載されていた。
f:id:bitterharvest:20161212071918j:plain

舎利殿の内部には、仏舎利(釈迦の遺骨)を安置した厨子がある。
f:id:bitterharvest:20161211072410j:plain
f:id:bitterharvest:20161211072458j:plain

舎利殿の周りには、鎌倉でよく見かける「やぐら」があった。
f:id:bitterharvest:20161211074456j:plain

舎利殿の奥の開山堂には、さらに建物があり、無学祖元の像が安置されていた。
f:id:bitterharvest:20161211073024j:plain

また、舎利殿の右横には禅堂があり、修行僧はここで座禅を組むそうである。7日間寝ずに座禅を組む修行も含まれているそうで(午後11時から2時まで横にならずに坐禅の姿勢のままで休む。座睡という)、ゆめゆめ臨済宗の僧侶になりたいと思ってはいけないと感じた。修行僧たちは、ここで、畳一枚での生活をする。座禅を組むときはその半分となる。円覚寺には25人の修行僧がいるとのこと。臨済宗のお寺の中では最大の人数だそうだ。
f:id:bitterharvest:20161211073818j:plain

この後、今日のもう一つの行事を楽しむため大方丈へと向かう。方丈は、大きさを表し、一辺が一丈、即ち、3メートルの正方形である。これが転じて、禅寺での住職の居室あるいは寺の住持を表すようになった。円覚寺の大方丈も、元々は、住職の居場所だったそうだが、禅を広めるために、一般に開放したそうだ。
f:id:bitterharvest:20161211084232j:plain
大方丈の裏には庭園がある。
f:id:bitterharvest:20161211084437j:plain

修行僧の足元にも及ばないのだが、その後、大方丈の横の建物で1時間ほどの座禅をして、帰路に着いた。

初冬にもかかわらず、真っ赤に色づいたもみじに迎えられて、普段見ることができない舎利殿、その内部、さらには、開山堂まで鑑賞することができ、さらには、初めての座禅を体験することができ、有意義な一日であった。

寒くなったらボルシチ

野菜売り場の店頭でビーツを見かけることが多くなった。先日のテレビによれば、昨年に比べて7倍も売り上げが増えたと野菜売り場の担当者が伝えていた。

ビーツは、英語ではbeetrootという。赤蕪とも聞いていたので、カブの一種かと思っていたが、そうではない。ビーツはアカザ科なので、ほうれん草や甜菜の仲間だそうだ。ビタミンや鉄分を多く含むということで、健康野菜として注目され、近年、使う人が増えてきたようである。

ビーツを使った料理と言えば、ボルシチだ。ロシア料理として紹介されることが多いが、本当は、ウクライナの家庭料理である。ソ連邦から分離したウクライナは、クリミア半島の帰属をめぐって、一昨年ロシアと激しく対立したことは、まだ、記憶に新しい。首都はキエフで、世界史の教科書にも出てくる都市だ。一度は訪れてみたいと思っている古都だ。

本格的なボルシチの料理を食べたのは、17年も前のことになる。同僚のロシア人、実は、ウクライナの出身だった彼を蓼科へ招待したことがきっかけである。そのときのお礼にということで、彼の家に招かれた時に、やはりウクライナ出身の奥さんの手料理であるボルシチをご馳走になった。素晴らしい味であったが、それにもまして、鮮やかな赤がとても印象的だった。

ビーツの話をあちらこちらで聞くうちに、色彩が印象に残っていた料理の思い出がよみがえり、一度作ってみたいと思うようになった。本来ならば、彼の奥さんからレシピを聞けばよいのだが、急に思い立ったので、日本語と英語の料理関連のホームページを手繰っての作品となった。本格的とはいかないかもしれないが挑戦した。

シチューを作るのと同じ要領なのだが、ビーツとサワークリームを使うことに特徴がある。以前にビーツを見かけたことのあるお店に出かけたが、残念ながら手に入れることができず、今回は缶詰を用いることにした。

例によって、今回の料理の仲間たちだ。
f:id:bitterharvest:20161210075910j:plain

主役のビーツが缶詰の中に納まっているのは残念だ。ビーツそのものは相当に硬そうな根菜なので、缶詰を用いれば下ごしらえの手間を省ける。最初のステップとしては悪くない選択だ。

最初は、スープの素を作る。カレー用の牛肉(250g)を湯通しして臭みを抜く。
f:id:bitterharvest:20161210082608j:plain

湯通しした熱湯は捨てて、牛肉が残った鍋に水(900cc)とマギーブイヨン(1個)を加えて、15分ほど煮る。
f:id:bitterharvest:20161210083000j:plain

この間十分な時間があるので、野菜の下ごしらえをする。セロリ(1/2本)とキャベツ(1/4個)は1cm幅に切る。トマト(2個)は熱湯をかけて湯むきをした後、ざく切りにする。ジャガイモ(2個)は一口大に切って水に浸しておく。

さらに、玉ねぎ(1個)とニンニク(1片)はみじん切りにする。
f:id:bitterharvest:20161210100921j:plain

別のフライパンを用意して、バター(2個、大さじ2程度)と玉ねぎ、にんにくを加える。
f:id:bitterharvest:20161210083749j:plain
これを、野菜に透明感が出るまで炒めて、赤ワインビネガー(大匙2杯)、砂糖(小匙1杯)、塩(小匙1/2杯)を加えて、ひと煮たてする(ビネガーが嫌いな場合には赤ワインで代用)。
f:id:bitterharvest:20161210084508j:plain

これを、牛肉を15分間煮た鍋に加える。
f:id:bitterharvest:20161210084635j:plain

さらに、キャベツ、セロリ、トマトを加える。
f:id:bitterharvest:20161210084737j:plain

そしてこれを10分ほど煮る。この間、時間があるので、ビーツの下ごしらえをする。
ビーツは缶詰半分ほどを用い、少し太めにせん切りにする。
f:id:bitterharvest:20161210085102j:plain

煮終わったところで、
f:id:bitterharvest:20161210085334j:plain

ビーツとジャガイモ、さらには缶詰のビーツの汁(半分)を鍋に加える。
f:id:bitterharvest:20161210085517j:plain

ジャガイモに味がしみ込んだ方がおいしくなるので、最初は中火でその後弱火にして30分ほど煮込む。
f:id:bitterharvest:20161210085642j:plain

出来上がったボルシチを器に移し、この上にパセリを加え、さらに、サワークリーム(90cc)と生クリーム(50cc)を混ぜたものを適量(大匙1-2杯)加える。
f:id:bitterharvest:20161210090245j:plain

サワークリームの味と、少しコリコリするビーツがまじりあって、おいしくいただけた。

少し残ったので、今朝もいただいた。ビーツの赤とサワークリームの白が混じりあい、ピンク色となったボルシチは見た目にもきれいだ。
f:id:bitterharvest:20161210090612j:plain

今度、機会があれば、同僚のウクライナ出身の奥さんにレシピを伺い、本格的なボルシチに挑戦してみたい。

秋深き伊豆修善寺を訪れる

11月末(27日―30日)に別荘の冬仕度をするために伊豆に出かけた。旅行する3日前(24日木曜日)には、東京では観測史上初の11月の積雪を記録した。我が家の庭もちょっとした風情を感じさせる冬景色になった。
f:id:bitterharvest:20161204183058j:plain

伊豆は暖かいところと思われがちだが、別荘のある地帯は箱根と同じように冬は厳しい。まだ、雪が残っているのではないかと心配して出かけたのだが、案の定、登っていくうちに道端の雪が増えてきて、駐車場の入口は吹き溜まりの雪で封鎖されていた。仕方なく、到着した日は雪かきに精を出すことになってしまった。ベランダにもたくさん残っていたので、記念に写真を撮った。
f:id:bitterharvest:20161204183725j:plain

次の日は伊豆修善寺の虹の郷を訪れた。昨日までライトアップしていたとのこと、まだ十分に楽しめた。日本庭園の近くのもみじは下り7分で、地面も朱色に染まっていて、深まり行く秋の景色を醸しだしていた。
f:id:bitterharvest:20161204193124j:plain
f:id:bitterharvest:20161204193154j:plain
f:id:bitterharvest:20161204193228j:plain

今年は、夏目漱石没後100年で、漱石にちなんだ話をあちらこちらで耳にする。NHKは「夏目の妻」を放映した。漱石の妻は悪妻として知られているが、尾野真千子は、癇癪持ちの漱石に耐えながらも、段々に自己を確立していくチャーミングな女性を演じた。表情がとても豊かで、ほのぼのとした温かみを感じさせてくれ、上手な女優さんだなと感心した。そのドラマの中で、夏目の胃潰瘍が悪くなり、修善寺の旅館で、妻鏡子の手厚い介護のもと療養する場面がある。そのとき滞在した旅館の一部(漱石が滞在していた部屋を含む)が虹の郷に移築されている。里山の佇まいを感じさせ、移築前よりも美しい背景の中に溶け込んでいるのではと想像させられる。
f:id:bitterharvest:20161204194249j:plain

日本庭園にほど近い匠の村はこれかららしく、まだ、緑が多かった。
f:id:bitterharvest:20161204200937j:plain

少し離れたところには、二季咲きの桜があったが、冬が迫っている冷たい空気の中、ただ寂しい。
f:id:bitterharvest:20161204201212j:plain

3日目は、修善寺の温泉街に出かけた。最初に、空海(弘法大師)が平安時代初期(807年)に開基した修禅寺を訪れた。最近の観光地は、外国人か老人で占められているが、ここは後者で溢れていた。
f:id:bitterharvest:20161204202040j:plain
修禅寺の庭園が運よく開園していたので、立ち寄った。
f:id:bitterharvest:20161204202151j:plain
f:id:bitterharvest:20161204202231j:plain
f:id:bitterharvest:20161204202335j:plain

伊豆は源頼朝が流された地のため、各所に源氏ゆかりの遺跡がある。修善寺も例外ではないが、しかし、暗い印象を伝えるものが多い。

二代将軍頼家は北条氏との政争に敗れて修善寺に流され、北条時政により入浴中に殺害された。彼の墓は温泉街の中心部の近くにある。
f:id:bitterharvest:20161204203206j:plain
そのそばには、母の北条政子によって、供養のために建立された指月堂がある。
f:id:bitterharvest:20161204203507j:plain
また、温泉街のはずれの山の麓に頼朝の弟の範頼の墓がある。範頼は義経とともに木曽義仲平氏の討伐に功績を挙げた武将である。二人とも、朝廷から官位を受けたために頼朝から疑われ追われる身となる。範頼は修善寺に幽閉され、梶原景時に攻められ、自害する。
f:id:bitterharvest:20161204204609j:plain

二人の武将の非業の死を悲しむように修善寺のもみじは鮮やかな朱色であった。
f:id:bitterharvest:20161204204752j:plain
f:id:bitterharvest:20161204204827j:plain

カレー風味のニョッキ

昨日、近くのカルディで三色ニョッキを手に入れた。ニョッキはジャガイモと小麦粉から作られるイタリア料理だ。そこに、トマトを加えると赤に、ほうれん草だと緑になる。これを利用したのが三色ニョッキだ。

ニョッキの由来をウィキペディアで調べてみると、その語源は、「塊」を意味するゲルマン語系の単語knokkaである。もともとは小麦粉を練って作っていた。アメリカ大陸からジャガイモが持ち込まれた後、これを用いるようになったそうだ。

ニョッキを見るとすいとん(水団)を連想することが多い。すいとんは小麦粉を練って作る。ニョッキもすいとんも元々は同じものであったかもしれない。ウィキペディアによれば、すいとん室町時代書物には表れてくるそうだ。これよりも古い歴史を持っているのがそばがき(蕎麦掻き)だ。これは小麦粉の代わりにそばを用いる。同じくウィキペディアによれば、そばがきは鎌倉時代には存在したそうだ。

すいとんもそばがきもあまりいいイメージがない。特に、そばがきには悪い印象がまつわりついている。食糧事情があまりよくなかった戦後の時代に、北海道の親せきから暮れになると半端でない量のそば粉が送られてきた。そばにでもと思って送ってきたのだろうが、そばの打ち方を知らない両親は、そばがきにしてくれた。一日か二日ならばおいしいと思ったのだろうが、何日も続けて食べさせられると、見るのも嫌になった。

すいとんも同じように何もない時に食べさせられた記憶があるので、すいとんもそばがきも出会いたくない料理だ(同じような理由で母は戦時中にこればかり食べさせられたというカボチャが嫌いだった)。

すいとんやそばがきを連想させるニョッキはこれまでは避けていたが、赤や緑の色が醸し出す茶目っ気さがこれまでの抵抗感を和らげてくれ、料理に使うことにした。

ニョッキが主張しすぎると、すいとんやそばがきにまつわる芳しくない思い出が呼び起こされるだろうから、少し強い味にしてみようと考え、カレー風味にすることとした。幸い、中村屋のカレー粉が冷蔵庫にしまってあるので、ちょっと高級なカレー味になるようにということで料理を始めた。

今日の食材の仲間たちは、次のとおりである。中央、左側に控えているのが、今日の主役の三色ニョッキである。そして、右側には脇役のシイタケとベーコンである。残りの連中は種類は多いが全て味付け役だ。
f:id:bitterharvest:20161123165802j:plain

まずは、イタリア料理の定番、ニンニク(2かけ)をオリーブオイル(大匙2杯)で炒める。弱火でニンニクの焼けたにおいが出てくるまで続ける。
f:id:bitterharvest:20161123170528j:plain

その後、ベーコン(100g程度)とシイタケ(2個)、さらに、日本酒(大匙2杯)を加えて、中火にして軽く炒める(本当は白ワインを使いたかったのだが、生憎、持ち合わせていなかった)。
f:id:bitterharvest:20161123170811j:plain

次に、牛乳(200CC)、カレー粉(大匙1杯)、パプリカ、クミンハウダー、塩、コショウ(それぞれ少々)を加えて、中火で煮詰める。
f:id:bitterharvest:20161123171100j:plain

鍋にお湯を沸かし、沸騰したところで、塩(大匙1杯)を加える。そして、三色ニョッキを鍋に入れ、水面に浮かび上がってくるまで煮立てる(大体3分程度)。
f:id:bitterharvest:20161123171326j:plain

ニョッキを網ですくって皿に移す。
f:id:bitterharvest:20161123171447j:plain

カレー風味をニョッキの上に注ぐ。
f:id:bitterharvest:20161123171620j:plain

イタリア料理らしくするために、イタリアンパセリとパルミジャーノを用意する。
f:id:bitterharvest:20161123171737j:plain

これを料理の上にパラパラとふってできあがりだ。
f:id:bitterharvest:20161123171823j:plain

食卓にはこのような感じで登場した。
f:id:bitterharvest:20161123171911j:plain

悪い思い出がよみがえることもなく、おいしくいただけた。

プログラムでの圏の構成を完成させる

4.7 C++プログラムから圏を作成する(続き)

前回の記事で、曜日を進めるプログラムの開発状況を手順を追いながら、説明した。このプログラムは、曜日を進める関数\(increase\)と遅らせる関数\(decrease\)から出発した。最初に作った関数は、値をどこにも記憶しない純粋な関数の集まりであった。

しかし、新たな要求が発生したために、呼ばれた関数をログとして出力することが要求された。最初に最も安易な実現方法を示した。それは、グローバル変数にログを記憶するというものであった。プログラム開発に馴染んでいない初心者が陥りやすいミスの一つだが、プログラムを開発するときに心掛けなければならない参照の局所性を犯している。これは重大な欠陥で、一つの事項の変更がプログラムのあちらこちらの変更に砂がるため、後々のプログラムの改変を困難なものにしてしまう。

上記の問題を改善するために、ログを局所変数化して、それを、関数の引数で引き渡すようにした。プログラムは、随分と改善されたのだが、しかし、引数として渡された変数は、その関数での直接的な関心事ではない。恐らく、プログラムが完成してからしばらくたつと、その変数がなぜ渡されてきたのだろうと疑問に思うことになるだろう。これは、関心の分離というもう一つのプログラム開発に当たって注意しなければならない事項を無視していたために生じた。

そこで、それぞれの関数は、不必要なものは一切有しない純粋な関数にして、関数の合成で、要求仕様の変更に対応した。この時の説明で変だなと思った人も多かったのではないかと思う。数学の力が強い人なのだろうと推察する。二つの関数\(f:a \rightarrow b,g:b \rightarrow c\)があった時、それらの関数の合成は、\(h=g \circ f : a \rightarrow c\)である。

これは、プログラムでは次のようになる。

function<c(a)> h(function<b(a)> f, function<c(b)> g) {}

ところが、関数の合成は次のようになっていた。

function<pair<int, string>(int)> compose(function<pair<int, string>(int)> f, function<pair<int, string>(int)> g)
{
	return [f, g](int x) {
		auto p1 = f(x);
		auto p2 = g(p1.first);
		return make_pair(p2.first, p1.second + p2.second);
	};
}

必要なところだけを切り出すと、\(f: int \rightarrow (Int,String), \ g: int \rightarrow (Int,String) \)となっている。

圏論での約束は、\(f\)のコドメインと\(g\)のドメインが一致していなければならないと謳っている。しかし、\(f\)のコドメインは\((Int,String)\)であるにもかかわらず、\(g\)のドメインは\(Int\)である。一致していない。このようなものを、どのようにして合成するのかという疑問がわく。これは、正しい疑問である。

3)クライスリ圏

数学は、公式に縛られる窮屈な世界だと思っている人も多いと思う。実は、そんなことはない。少し、例外的なものが発生したときは、それを含むように、概念を拡張してあげればよい。それによって、新しい体系の数学を作ることができる。

今回の場合も同じようなものだ。\(g\)のドメインは\(Int\)だ。\(f\)のコドメインには\(Int\)が含まれているので、これを利用して、射を合成できるように規則を拡張したらどうだろうかという発想が生まれる。

例えば、二つの対象\(A,B\)に対して(射\(f\)は元々は\(f: A \rightarrow B\)であったのだが)、何らかの要請で、\(f: A \rightarrow (B, C)\)とする必要が発生した。そこで、圏論での約束を少し緩めて、二つの対象\(A,B\)にして、射\(f: A \rightarrow (B, C)\)を射として認めるようにしたらどうであろうか。

この例で行くと、\(increase\)は、元々、\(Int\)から\(Int\)への関数であった。\(decrease\)も同じである。しかし、ログを作成できるようにという要求に合わせるために、これらは\(Int\)から\((Int, String)\)への関数へと変化した。

曜日を進めるプログラムがどのような圏になるかを直感的に理解してもらうために、まず、図を見てもらおう。
f:id:bitterharvest:20161118151412p:plain

そこで、\(increase\)のドメインを\(Int\)とし、整数(曜日)と文字列の対であるコドメインを\(\mathcal{M}(Int)\)で表すこととしよう。即ち、\(increase:Int \rightarrow \mathcal{M}(Int)\)とする。\(decrease,stay\)についても同様である。

そこで、これらの関数は合成するときは、\(\mathcal{M}(Int)\)を\(Int\)に変換する必要がある。関数の合成にはこの機能を持たせることにしよう。そうすると、\(compose(increase,decrease)\)は、図に示したように、\(increase\)を実行した後で、\(decompose\)を実行し、最後に\(decrease\)を実行すると読むことができるので、これらの、ドメインとコドメインの関係は
\begin{eqnarray}
increase: Int \rightarrow \mathcal{M}(Int) \\
compose: \mathcal{M}(Int) \rightarrow Int \\
decrease: Int \rightarrow \mathcal{M}(Int)
\end{eqnarray}
となり、関数の合成に関する約束(合成される関数のコドメインと合成する関数のドメインは一致する)を守ることができる。

次のstayの関数について考えよう。この関数は恒等射と考えているので、入力された曜日はそのままである。またこれまでに実行してきた関数の列に対しても変化を加えてはいけないので、ここでは関数の名前\("stay"\)を出力するのではなく、空の文字列""を出力する。

圏の形になってきたので、その構成を示そう。
1) 対象:\(Day=\{0,1,2,3,4,5,6\}\)
2) 射:\(increase, decrease\)
3) ドメイン:\(Day\)、コドメイン:\(\mathcal{M}(Day)\)
4) 恒等射:\(stay\)
5) 合成:\(compose\)
① 結合律:満足
② 単位律:満足

結合律、単位律は、プログラムの内容から満たされていると判断できるが、念のため、正しいかどうか調べてみよう。次のような\(main\)のプログラムを作成して検査してみることにした。
最初の2行は恒等射となっている\(stay\)に関するものである。次の4行は、\(compose\)の実行順序によらないことを示すために、左側から実行する場合とそれとは逆の場合で変化が生じるかを調べるものである。

int main()
{
	auto h = compose(stay, decrease);
	auto k = compose(decrease, stay);
	auto p = compose(decrease, compose(increase, decrease));
	auto r = compose(compose(decrease, increase), decrease);
	auto s = compose(decrease, compose(decrease, compose(increase, decrease)));
	auto t = compose(compose(compose(decrease, decrease), increase), decrease);
	auto a = h(3);
	auto b = k(3);
	auto c = p(3);
	auto d = r(3);
	auto e = s(3);
	auto f = t(3);
	cout << a.first << endl;
	cout << a.second << endl;
	cout << b.first << endl;
	cout << b.second << endl;
	cout << c.first << endl;
	cout << c.second << endl;
	cout << d.first << endl;
	cout << d.second << endl;
	cout << e.first << endl;
	cout << e.second << endl;
	cout << f.first << endl;
	cout << f.second << endl;
	return 0;
}

プログラムの実行結果を以下に示す。いずれの場合も予想通り正しい動きをした。
f:id:bitterharvest:20161118163202p:plain

このように純粋な関数と、その合成、および、恒等射としての役割を持つプログラムで構成された圏は、クライスリ(Kleisli)圏と呼ばれる。

また、クライスリ圏はモナド(Monad)と呼ばれるものに含まれる。これについては、また、後の記事で詳しく説明する。

なお、使用された関数のロゴを出力してくるところについてはあまり詳しく説明しなかったが、この部分はモノイド圏になっていることに注意してほしい。

追:\(compose\)については、Milewski氏が圏論の説明をする時に使っていたものをそのまま利用させてもらった。紙面を借りてお礼申し上げる。

C++のプログラムも圏に変えてしまおう

4.7 C++プログラムから圏を作成する

いろいろな圏を見てきたので、ここでは、プログラマーにとっては大事なプログラムを圏として構成することを考えよう。

1)曜日を進めるプログラム

ここで、作成するプログラムを曜日を進めたり遅らせたりするプログラムだ。曜日は数字で表わし、日曜日は0に、月曜日は1というように、日曜日からの昇順で表わすことにしよう。

プログラムに用いる言語は、多くのプログラマが馴染んでいる命令型言語(Imperative Programming Language)を用いることする。ここではC++を使ってみることにしよう。とても久しぶりだが、新しい発見があるかもしれない。そこで、急遽、パソコンにVisual Stadio Communityをインストールし、C++を使えるようにした。開発中の画面を紹介しよう。
f:id:bitterharvest:20161116171747p:plain
上の画面は、ここで紹介するプログラム開発の最終場面である。左側の大きなウィンドウが編集用の画面で、右下の黒いウィンドウが実行画面である。プログラムを編集した後に、[Build]→[Build Solution]で実行ファイルを作成し、[Debug]→[Start Without Debugging]でプログラムを実行できる。編集機能もしっかりしているので、初めてのVisual Studioであったが、プログラムは簡単に作成することができた。

プログラミングをするときには、必要な機能を定めることから始まる。曜日を進めたり、遅らせたりといっているので、一日だけ曜日を進める関数と遅らせる関数が必要になるだろう。これらは、\(increase\)と\(decrease\)という名前を付けて用意しよう。これらの関数は、曜日\(x\)に1を加え、あるいは1減じてそれを7進数で表せばよいので、以下のようなプログラムとなる。\(main\)には、これらの使用例を記述した。

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

int increase(int x)
{
	return (x + 1) % 7;
}

int decrease(int x)
{
	return (x - 1) % 7;
}

int main()
{
	cout << increase(3) << endl;
	cout << decrease(4) << endl;
	cout << increase(2) << endl;
	return 0;
}

簡単なプログラムなので問題はないだろう。ところで、プログラムを作成していると変更が生じるのは、日常茶飯事である。上記のプログラムを実現した後で、呼ばれた関数名のログを作成するようにと要求されたら、どのように応えたらよいであろうか。

次のようなプログラムで対応する魅力に駆られる人も多いことであろう。グローバル変数として\(log0\)を用意し、それぞれの関数の中で、呼ばれるたびに、自身の名前を\(log0\)に付け加える。プログラムで示すと次のようになる。

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

string log0 = "";

int increase(int x)
{
	log0 += "increase; ";
	return (x + 1) % 7;
}

int decrease(int x)
{
	log0 += "decrease; ";
	return (x - 1) % 7;
}

int main()
{
	cout << increase(3) << endl;
	cout << decrease(4) << endl;
	cout << increase(2) << endl;
	cout << log0 << endl;
	return 0;
}

上記のプログラムは、変更箇所が少ないので、将来の変更を考えない人は、この魅力に惑わされてしまう。しかし、このプログラムは、将来の変更には脆弱である。例えば、\(log0\)という名前がよくないので変更ということになると、全ての関数がその影響を受ける。名前の変更程度ならよいが、最近人気が出てきている並列処理で実行できるようにしたいとなった時、\(log0\)にアクセスしているすべての場所で変更が要求される。

これは、プログラムが参照の局所性(Locality of Reference)を守っていないことによる。そこで、引数で渡すことにして、次のように、プログラムを実現した。

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

pair<int, string> increase(int x, string log0)
{
return make_pair((x + 1) % 7, log0+"increase; ");
}

pair<int, string> decrease(int x, string log0)
{
return make_pair((x - 1) % 7, log0 + "decrease; ");
}

int main()
{
string log0 = "";
auto a = increase(3, log0);
auto b = decrease(4, a.second);
auto c = increase(2, b.second);
cout << a.first << endl;
cout << b.first << endl;
cout << c.first << endl;
cout << c.second << endl;
return 0;
}

かなり見やすくなってはいるのだが、それぞれの関数で\(log0+...\)とあるのが気になる。それぞれの関数で、\(log0\)がなんであるかは知らなくてもよいことのように思われる。関係ないものを分離することを関心の分離(Separation of Concerns)というが、個々の部分はこの原理を犯しているように思われる。

そこで、プログラムをさらに改善することにする。関数\(increase\)と\(decrease\)はそれぞれ、計算の結果と関数の名前を対にして出力するように改める。このようにすれば、それぞれの関数は、その関数に求められている必要最小限のことだけを行い、それ以外のことはしないようにすることができる。

2)圏に移す

これらの関数は次から次へとと呼ばれるが、これは、関数の合成で表すこととしよう。即ち、二つの関数\(f:a\rightarrow b,g:b\rightarrow c\)がこの順番で呼ばれた時、\(h=g \circ f : a \rightarrow c\)となるようにしよう。
プログラムは次のような形になる。

function<c(a)> h(function<b(a)> f, function<c(b)> g) {}

また、この関数の戻り値は、関数の本体である。これはラムダ関数として返すようにする。これに注意して、\(compose\)を実現してみよう。

function<pair<int, string>(int)> compose(function<pair<int, string>(int)> f, function<pair<int, string>(int)> g)
{
	return [f, g](int x) {
		auto p1 = f(x);
		auto p2 = g(p1.first);
		return make_pair(p2.first, p1.second + p2.second);
	};
}

プログラム全体を示すと以下のようになる。

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

pair<int, string> increase(int x)
{
	return make_pair((x + 1) % 7, "increase; ");
}

pair<int, string> decrease(int x)
{
	return make_pair((x - 1) % 7, "decrease; ");
}

function<pair<int, string>(int)> compose(function<pair<int, string>(int)> f, function<pair<int, string>(int)> g)
{
	return [f, g](int x) {
		auto p1 = f(x);
		auto p2 = g(p1.first);
		return make_pair(p2.first, p1.second + p2.second);
	};
}


int main()
{
	auto h = compose(increase, decrease);
	auto p = compose(decrease, compose(increase, decrease));
	auto r = compose(decrease, compose(decrease, compose(increase, decrease)));
	auto a = h(3);
	auto b = p(3);
	auto c = r(3);
	cout << a.first << endl;
	cout << a.second << endl;
	cout << b.first << endl;
	cout << b.second << endl;
	cout << c.first << endl;
	cout << c.second << endl;
	return 0;
}

mainで、関数をいくつか合成し、実験してみた。最初の合成は、
\(increase \circ decrease\)である。この合成関数は\(h\)という名前がつけれらている。値を入力すると実行される。
これに続いて\(decrease \circ increase \circ decrease\)と\(decrease \circ decrease \circ increase \circ decrease\)の合成関数を用意した。これらは\(p,r\)という名前がつけれらている。
実行結果は最初の画面の右下の黒いウィンドウである。

関数の合成がを用意したので、圏とするためには、恒等射が必要である。これは、曜日を進めもしなければ遅らせもしない関数である。\(stay\)という名前にして、もらった曜日をそのまま返すようにしよう。なお、関数名はブランクで返すこととする(恒等射にするためだが、説明は後にする)。即ち、

pair<int, string> stay(int x)
{
	return make_pair(x, "");
}


プログラムの全体を示すと次のようになる。

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

pair<int, string> increase(int x)
{
	return make_pair((x + 1) % 7, "increase; ");
}

pair<int, string> decrease(int x)
{
	return make_pair((x - 1) % 7, "decrease; ");
}

pair<int, string> stay(int x)
{
	return make_pair(x, "");
}

function<pair<int, string>(int)> compose(function<pair<int, string>(int)> f, function<pair<int, string>(int)> g)
{
	return [f, g](int x) {
		auto p1 = f(x);
		auto p2 = g(p1.first);
		return make_pair(p2.first, p1.second + p2.second);
	};
}

int main()
{
	auto h = compose(increase, decrease);
	auto p = compose(decrease, compose(increase, decrease));
	auto r = compose(decrease, compose(decrease, compose(increase, decrease)));
	auto s = compose(stay, compose(decrease, compose(decrease, compose(increase, decrease))));
	auto a = h(3);
	auto b = p(3);
	auto c = r(3);
	auto d = s(3);
	cout << a.first << endl;
	cout << a.second << endl;
	cout << b.first << endl;
	cout << b.second << endl;
	cout << c.first << endl;
	cout << c.second << endl;
	cout << d.first << endl;
	cout << d.second << endl;
	return 0;
}

ここまでできたので、次は、これを圏として構成してみよう。少し、説明が長くなりそうなので、記事を改めることにする。

二項演算子からモノイド圏を作る

前回の記事は、ホモトピー論まで含まれていたので、とても高度な数学的概念が含まれていた。それにもめげず、沢山の人が記事を読んでくださったようで、感謝している。今回は現実の世界に戻して、二項演算子の世界を圏にすることを考えよう。

4.6 二項演算子からの圏

単純な圏から複雑な圏へと話を進めてきたが、対象が一つで、射が複数あるいは無数の圏を考えてみよう。小学校で一番最初に学ぶ数学の概念は加算である。二つの自然数を足し合わせて自然数を得るという考え方を学んだのは、記憶の遠くにある小学校の1年生の頃だ。教育熱心の親に育てられた人であれば、すでに、幼稚園の時に学んでいる可能性もある。頭の中に定着している考え方を圏論という立場から整理しなおしてみよう。

小学校の1年生の時に習った足し算は自然数を相手にしていたが、ここでは、そうではなくて整数を相手にするととにしよう。そうすると、足し算は二つの自然数を得て、足した結果(これも自然数になる)を出力する。Haskellでもそのようになっている。

Prelude> 3 + 4
7

このように二つの計算しようとする数の真ん中に置かれる演算子二項演算子と呼ばれる。あるいは中置関数とも呼ばれる。しかし、関数を用いるときは、一般的には、関数名を書いた後で、変数を並べるのがふつうである。Haskellはこのように記述することも許されている。例えば、足し算の場合には、次のように書くことができる。

Prelude> (+) 3 4
7

1)加法演算子から圏を作成する

これをそのまま圏論の射にしようとすると、射のドメインは二つの整数の対、コドメインは一つの整数となってしまう。このため、演算子の合成(足し算を繰り返し行うこと)をうまく説明することができない。ドメインとコドメインを同じ対象とするためには、入力する整数の数を一つにする必要がある。これは、足される数を演算子の中に含めることで実現できる。Haskellもこれを用意していて、次のように利用することができる。このように多変数の関数を一変数のそれにすることをカリー化(Currying)という。

Prelude> (+3) 4
7

これは一つの圏をなしているが、図で表すと次のようになる。
f:id:bitterharvest:20161115102031p:plain

構成は次のようになっている。
1) 対象:整数\({\mathbb Z}\)
2) 射:\( (+i) \) ここで\(i \in {\mathbb Z}\)
3) ドメイン、コドメイン:整数\({\mathbb Z}\)
4) 恒等射:\( (+i) \)
5) 合成:\( (+i) \circ (+j) = (+ (i+j) ) \)
① 結合律:満足
② 単位律:満足

Haskellでの合成の例を示しておこう。

Prelude> (+3) . (+4) $ 2
9

二項演算子を圏で表現することに成功したが、他には、方法がないであろうか。二項演算子を関数の合成とし、足される数と足す数をそれぞれ射にするのはどうであろうか。暗黙の裡に整数を集合として考えていたと思うが、モノの見方を全く変えて、これを射と考える。圏論では、射の方が先に来るので、慣れてくるともっともなのだが、集合と言う枠組みの中で考えていると、なかなかこのような発想は浮かばない。

足される数と足す数をそれぞれ射にすると、対象はどうなるのであろうか。射には、ドメインとコドメインが存在しないといけないが、これはシングルトン(Haskellでは()であらわす)ということにしよう。それでは、このように表した圏を図に描いてみよう。
f:id:bitterharvest:20161115104853p:plain

構成は次のようになっている。
1) 対象:シングルトン
2) 射:\(i \in {\mathbb Z}\)
3) ドメイン、コドメイン:シングルトン
4) 恒等射:\( 0 \)
5) 合成:\( i \circ j = i+j \)
① 結合律:満足
② 単位律:満足

上の例では、合成を加算と見なしていたが、除算と見なせば引き算が、乗算と見なせば掛け算が定義されたことになる(但し、割り算の結果が整数にならない。そうでなくても、ゼロでの割り算が定義されないばかりでなく、計算の順序にもよるので、即ち、\( (24 / 4 )/ 2 \neq 24 / (4 / 2) \)なので、結合律を満たさず、圏とはならない)。

2)あみだくじから圏を作成する

もう少し、馴染みのある例を挙げてみよう。あみだくじだ。今、3人であみだくじを引くことにする。三本の線を引くことになるが、線の置換は以下の6種類に限られる。
f:id:bitterharvest:20161115113646p:plain

そこで、置換前とその後の位置を行列で表し、これを置換行列と呼ぶことにしよう。そして、それぞれの置換行列には名前を付けることにしよう。このようにすると、6種類の置換は次のように表現できる。

\begin{eqnarray}
p_0 &=&
\begin{pmatrix}
1 & 2 & 3 \\
1 & 2 & 3
\end{pmatrix}
,\ p_1 =
\begin{pmatrix}
1 & 2 & 3 \\
2 & 1 & 3
\end{pmatrix}
,\ p_2 =
\begin{pmatrix}
1 & 2 & 3 \\
3 & 2 & 1
\end{pmatrix}
, \\
p_3 &=&
\begin{pmatrix}
1 & 2 & 3 \\
1 & 3 & 2
\end{pmatrix}
,\ p_4 =
\begin{pmatrix}
1 & 2 & 3 \\
2 & 1 & 2
\end{pmatrix}
,\ p_5 =
\begin{pmatrix}
1 & 2 & 3 \\
3 & 2 & 1
\end{pmatrix}
\end{eqnarray}

また、あみだくじの置換は、次の図のように、接続できるものとしよう。
f:id:bitterharvest:20161115115542p:plain

上の図では、\(p_1\)と\(p_1\)の置換行列を接続して新しい置換行列を作成した。新しい置換行列を\(p_2 \circ p_1\)としよう。

それでは二つの置換行列を合成したものを他にも求めてみよう。どの二つを合成しても、6種類の置換行列のどれかに対応することが分かる。
\begin{eqnarray}
p_0 \circ p_0 &=& p_0, \ p_1 \circ p_0 = p_1, \ p_2 \circ p_0 = p_2, \ p_3 \circ p_0 = p_3, \ p_4 \circ p_0 = p_4, \ p_5 \circ p_0 = p_5, \\
p_0 \circ p_1 &=& p_1, \ p_1 \circ p_1 = p_0, \ p_2 \circ p_1 = p_5, \ p_3 \circ p_1 = p_4, \ p_4 \circ p_1 = p_3, \ p_5 \circ p_1 = p_2, \\
p_0 \circ p_2 &=& p_2, \ p_1 \circ p_2 = p_4, \ p_2 \circ p_2 = p_0, \ p_3 \circ p_2 = p_5, \ p_4 \circ p_2 = p_1, \ p_5 \circ p_2 = p_3, \\
p_0 \circ p_3 &=& p_3, \ p_1 \circ p_3 = p_5, \ p_2 \circ p_3 = p_4, \ p_3 \circ p_3 = p_0, \ p_4 \circ p_3 = p_2, \ p_5 \circ p_3 = p_1, \\
p_0 \circ p_4 &=& p_4, \ p_1 \circ p_4 = p_2, \ p_2 \circ p_4 = p_3, \ p_3 \circ p_4 = p_1, \ p_4 \circ p_4 = p_5, \ p_5 \circ p_4 = p_0, \\
p_0 \circ p_5 &=& p_5, \ p_1 \circ p_5 = p_3, \ p_2 \circ p_5 = p_1, \ p_3 \circ p_5 = p_2, \ p_4 \circ p_5 = p_0, \ p_5 \circ p_5 = p_4
\end{eqnarray}

そこで、置換行列を射にしてあみだくじの圏を構成してみよう。
構成は次のようになっている。
1) 対象:シングルトン
2) 射:置換行列\(p_0,p_1,p_2,p_3,p_4,p_5\)
3) ドメイン、コドメイン:シングルトン
4) 恒等射:\(p_0\)
5) 合成:置換行列の接続
① 結合律:満足
② 単位律:満足

図で示すと次のようになる。
f:id:bitterharvest:20161115152209p:plain

3)モノイド圏

あみだくじが出てきたので、可換群を想像した人は、群論に詳しい人だと思う。

群論の中で一番単純な群は半群である。半群は次のように定義されている。

集合\(S\)とその上の二項演算子\(\circ : S \times S \rightarrow S\)が与えられた時、組\((S, \circ) \)が結合律を満たす時、これを半群という。

さらに、半群単位元を有するならば、これをモノイド群という。

モノイド圏は、これまで見たきたように、集合の要素を射に、二項演算子を射の合成に、そして、単位元を恒等射にしたものである。このため、モノイド群から作られたものであるので、モノイド圏という。

モノイド群といわれると複雑そうに見えるが、二項演算子を圏にしたものと考えれば納得いくだろう。

様々な関係から圏を作成してみよう

4.様々な圏の作成

圏に馴染むためにいくつかの例を挙げることにしよう。

4.1 空圏

圏の中でもっとも単純な圏は、対象も射も持たない。このため、恒等射も存在しないことになる。これは空圏(圏0)と呼ばれる。その構成を挙げておこう。
1) 対象:なし
2) 射:なし
3) ドメイン、コドメイン:なし
4) 恒等射:なし
5) 合成:なし
① 結合律:満足
② 単位律:満足

4.2 終端圏

空圏に続いて単純な圏は、対象と射を一つずつ持つ終端圏(自明な圏、圏1)である。これの構成は次のようである。
1) 対象:一つ\(T\)
2) 射:一つ\(id_T\)
3) ドメイン、コドメイン:\(T\)
4) 恒等射:あり\(id_T\)
5) 合成:\(\circ\)
① 結合律:満足、即ち、\( (id_T \circ id_T) \circ id_T = id_T \circ (id_T \circ id_T) \)
② 単位律:満足、即ち、\(id_T \circ id_T=id_T\)

まだ、関手(functor)の話をしていないが、圏を対象とし、圏から圏への弧を射にすると新たな圏を構成することができる。この圏での始対象となるのが空圏で、終対象となるのが終端圏である。

4.3 二集合と関数からの圏

二つの集合\(A,B\)とその間の関数\(f\)は、それぞれの集合に恒等射を用意することで、圏にすることができる。
1) 対象:集合\(A,B\)
2) 射:関数\(f\) 、及び、恒等射と合成された射
3) ドメイン:\(A\)、コドメイン:\(B\)
4) 恒等射:\(id_A,id_B\)
5) 合成:\(\circ\)
① 結合律:関数が一つなので満足
② 単位律:\(f \circ id_A = f = id_B \circ f\)とする。

図で例を示そう(終端圏の例も同時に示す)。
f:id:bitterharvest:20161107173827p:plain

4.4 グラフからの圏

射が写像だけではなく、関係も表すことができることを説明しよう。最初はグラフである。

グラフには方向のあるものとそうでないものがあるが、ここでは方向のあるものについて扱う。グラフは、節点(node)とそれを結ぶ弧(arc)によって構成される。
グラフからは、次のようにして圏が作成できる。
1) 節点(\(V_1,V_2,V_3,..\))を対象にし、弧(\(f_1,f_2,f_3,..\))を射とする。
2) さらに二つの連続している弧(片方の弧の終点と他方の弧の始点が同じ節点である)に対しては、これらを接続した弧を新たに作成し、射の中に加える。この操作を、新たな弧が作れなくなるまで繰り返す。
3) 各節点に対して、自身へ向かう弧を作成し、これを恒等射とする。

それでは例で示そう。
f:id:bitterharvest:20161109053956p:plain
1) 左上は与えられたグラフである。
2) 右上は、二つの連続する弧をつなげて加えたものである。
3) 左下は三つの連続した弧をつなげて加えたものである。
4) 右下は恒等射を加えたものである。

出来上がった圏は次のようになっている。
1) 対象:節点\(U,V,W,X,Y,Z\)
2) 射:弧\(f,g,h,k,p,q,r\),及び、恒等射と合成された射
3) ドメインとコドメイン: \(f:V \rightarrow W, g:W \rightarrow X, h:X \rightarrow Y, k:U \rightarrow Z\), \( p:V \rightarrow X, q:W \rightarrow Y, r:V \rightarrow Y \)
4) 恒等射:\(id_U,id_V,id_W,id_X,id_Y,id_Z\)
5) 合成:\(p=g \circ f, \ q=h \circ g, \ r=h \circ g \circ f =h \circ p =q \circ f \)
① 結合律:\((h \circ g) \circ f = h \circ (g \circ f)\)であるので満足している。
② 単位律:\(f \circ id_V = f = id_W \circ f,...\)であるので満足している。

4.4 順序からの圏

射が関係を表す例の二番手は順序である。順序は、量や質の差によって、順序付けを行うときに使う数学の概念である。順序付けの仕方には強い場合も弱い場合もあるが、その強弱によって、順序には、前順序(preorder)、半順序(partial order)、全順序(total order)の三種類が数学の世界では用意されている。

1)前順序

ATP男子のテニスツアーも一昨日(11月6日)全て終わり、2016年度のシングルスレースの順位が確定した。錦織は、幸い、5位の位置におりロンドンで開催されるATPファイナルに出場できることとなった(上位の8人がファイナルに出場できる。今年は、ナダルが8位だが、怪我のため出場しないので、9位のティエムが繰り上げで参加になった。また、4大オープンに優勝すれば順位に関係なく出場できる)。上位5人の今年度のポイントは次のようになっている。

順位名前ポイント
1マレー\(11,185\)
2ジョコビッチ\(10,780\)
3ワウリンカ\(5,115\)
4ラオニッチ\(5,050\)
5錦織\(4,705\)
ポイントによって、上記のように順位がつけられているけれども、マレーとジョコビッチのどちらが強いかと聞かれた時、戸惑う人が多いのではないだろうか(先週までは、ジョコビッチが1位だった)。二人のこれまでの対戦成績は、29対29と拮抗している。甲乙つけがたい。

しかし、マレーとワウリンカを比べたとき、どちらが強いかと問われた時、マレーだと多くの人が答えるのではないだろうか。対戦成績を比較すると9対7だ。ジョコビッチとはさらにひらいて19対5だ。

だが、ワウリンカは次に続くラオニッチや錦織よりは強そうだ。4大タイトルの試合で2回も優勝している。

このように考えると、上位5人は3グループに分けられそうだ。最強の2人(マレー、ジョコビッチ)、追いかける1人の勇者(ワウリンカ)、次の世代を担う2人(ラオニッチ、錦織)という具合だ。

そこで、この強さの関係を前順序で表すことにしよう。前順序は、マレーとジョコビッチのように、二者間で順序をつけがたい時、即ち、どちらとも言えない時に、用いると便利である。

前順序は、量あるいは質の違いを二項関係\(\leq\)で表し、次の要件が成立することが必要とされる。ここで、\(P\)は集合とし、集合の要素同士を比較しているものとする。
1) 反射律(reflexivity):任意の\(a \in P\)に対して、\(a \leq a\)である。
2) 推移律(transitivity):任意の\(a,b,c \in P\)に対して、\(a \leq b\)かつ\(b \leq c\)であれば、\(a \leq c\)である。

\(a \leq b\)を\(a\)は\(b\)よりも強くはないということにしよう(弱いか一緒である)。このように定めると、先の5人のテニス選手の集まりを集合\(P\)とした時、彼らの関係を次図のように表すことができる。
f:id:bitterharvest:20161108055209p:plain

図で節点はテニス選手を表し、それぞれの姓の頭文字で表してある。また、強くはないという二項関係は弧で表してある。また、マレーとジョコビッチのように、強弱がつけがたい場合には、マレーはジョコビッチよりは強くないという関係と、ジョコビッチはマレーよりは強くないという関係の両方を用いて表した。

上の図は、先ほどのグラフと似ていないだろうか。そこで、グラフから圏を求めたときと同じ方法で、この前順序集合を圏に変えてみよう。図に示すような手順で求められる。

f:id:bitterharvest:20161108063954p:plain
f:id:bitterharvest:20161108064010p:plain

出来上がった圏は次のようになっている。
1) 対象:選手\(N,R,W,D,M\)
2) 射:強弱関係 \(f,g,h,p,q,r,s,t,u,v,w,z\)、及び、恒等射と合成された射
3) ドメインとコドメイン: \(f:N \rightarrow R, g:R \rightarrow N, h:R \rightarrow W,... \)
4) 恒等射:\(id_N,id_R,id_W,id_D,id_M\)
5) 合成:\(u=h \circ f, \ v=p \circ h, \ w=q \circ p,...\)
① 結合律:\((p \circ h) \circ f = p \circ (h \circ f),...\)であるので満足している。
② 単位律:\(f \circ id_N = f = id_R \circ f,...\)であるので満足している。

2)半順序

位相空間(topological space)を取り上げてみよう。これにはアレルギーがある人も多いことと思う。数学を得意としていた人が、大学に入ってつまずくきっかけとなりやすいのが位相空間だ。ここでは、単に集合と考えてもらっても構わないので、気楽に読んでほしい。

今、全体集合\(X\)と二つの部分集合\(A,B\)が図のように与えられたとしよう。
f:id:bitterharvest:20161108081927p:plain

これから位相空間を作ることにしよう。位相空間を作るためには、開集合あるいは閉集合を用意する必要がある。ここでは、開集合を用意することにしよう。定義は次のようになっている。

位相空間は順序付けられた対\((X,T)\)である。ここで、\(X\)は集合であり、\(T\)は\(X\)の部分集合の集まりで、次の命題を満たす。
1) 空集合\(\{\}\)と\(X\)は\(T\)に属する。
2) \(T\)のメンバーのいかなる(有限でも無限でもよい)論理和も\(T\)に属する。
3) \(T\)のメンバーのいかなる有限の数の論理積も\(T\)に属する。

そこで、先に与えられた集合\(X\)と部分集合\(A,B\)から、\(T\)のメンバーを作成してみよう。
与えられた集合と空集合はメンバーに属すので、\(T\)は取り敢えず\(T=\{\{\},X,A,B\}\)となる。そこで、その他のメンバーを探してみよう。

まず、論理和の方から考えると、\(A \cup B\)が得られる。これを\(C=A \cup B\)と名付けよう。他にはなさそうである。メンバーをどのように取ってきてそれらの論理和を取ったとしても、現在のメンバーのどれかになってしまう。そこで、ここまでに得られたメンバーは\(T=\{\{\},X,A,B,C=A \cup B\}\)である。

次に論理積について考えよう。\(A \cap B\)が得られる。これを\(D=A \cap B\)と名付けよう。他にはなさそうである。ここまでに得られたメンバーは\(T=\{\{\},X,A,B,C=A \cup B,D=A \cap B\}\)である。

新たなメンバーが増えたので、もう一度論理和を考える。新しく加わるものはないので、\(T=\{\{\},X,A,B,C,D\}\)となる。
f:id:bitterharvest:20161108081949p:plain
ここで、最初に与えられた集合から位相空間\((X,T)\)を作成することができた。位相空間では、\(T\)のメンバーは集合なので、含むか含まないかの関係を有する。そこで、\(A \leq B\)を\(A\)は\(B\)に含まれるということにすると、\(T\)のメンバーは順序付けすることができる。これは、以下のようなハッセ図となる。
f:id:bitterharvest:20161108082018p:plain

ハッセ図は、半順序集合になっているのだが、半順序をまだ定義していない。そこで、定めておこう。前順序の時と同じように、集合\(P\)の要素同士を比較しているものとする。半順序集合は次の要件を満たすものである。
1) 反射律(reflexivity):任意の\(a \in P\)に対して、\(a \leq a\)である。
2) 推移律(transitivity):任意の\(a,b,c \in P\)に対して、\(a \leq b\)かつ\(b \leq c\)であれば、\(a \leq c\)である。
3) 反対称律(asymmetry):任意の\(a,b \in P\)に対して、\(a \leq b\)かつ\(b \leq a\)であれば、\(a = b\)である。

反対称律は、二つの要素の間には、高々一つの関係しか存在しないことをうたっている。前順序集合では、二つの要素の間に二つの関係が成り立つことを認めていた。テニス選手の例でいえば、錦織とラオニッチの間は甲乙つけがたいということで、\(N \leq R\)と\(R \leq N\)という二つの関係を用意した。

しかし、半順序集合ではこのようなことは許されない。\(N \leq R\)と\(R \leq N\)であれば、\(N = R\)となり、錦織とラオニッチは同じということになる。二人の異なる人間が同じということは何となく気持ちが悪いので、テニス選手の強さを表す時は、半順序ではなく前順序で表した。

前順序では循環(サイクル)が生じることがあるが、半順序では循環が生じない。一方向に進むグラフとなる。それでは、先のハッセ図から圏を求めてみよう。ここでは、答えだけにすると、下図のようになる。
f:id:bitterharvest:20161108104136p:plain

出来上がった圏は次のようになっている。
1) 対象:集合\(X,E,A,B,C,D\)
2) 射:包含関係 \(f,g,h,k,p,q,r,s,t,u,v,w,x,y\),及び、恒等射と合成された射
3) ドメインとコドメイン: \(f:E \rightarrow D, g:D \rightarrow A, h:D \rightarrow B,... \)
4) 恒等射:\(id_X,id_E,id_A,id_B,id_C,id_D\)
5) 合成:\(u=g \circ f, \ v=p \circ g \circ f, \ w=r \circ p \circ g \circ f,...\)
① 結合律:\((p \circ g) \circ f = p \circ (g \circ f),...\)であるので満足している。
② 単位律:\(f \circ id_E = f = id_D \circ f,...\)であるので満足している。

今、対象\(A\)から\(B\)への写像の集合を\({\rm Hom}(A,B)\)で表すことにしよう。
半順序の場合、任意の二つの接点を結ぶ弧は、最初に説明したように高々一つである。従って、任意の二対象\(A,B\)に対して\({\rm Hom}(A,B)\)の要素の数は高々一つである(空集合かシングルトン)。このように、任意の二対象に対して射の集合の要素の数が高々一つである圏を薄い圏(thin category)という。

薄い圏でかつ循環(サイクル)を有しないとき、全ての射はエピ射であるとともにモノ射である(証明は簡単なので試みること)。集合の世界では、単射全射である時は、逆関数があることが保証されていた(これを双射(bijective)という)。しかし、循環(サイクル)を有しない薄い圏においては、それぞれの弧はエピ射でありモノ射であるにもかかわらず、逆向きの弧は存在しない(循環することはないため)。即ち、逆射に相当するものは存在しない。このため、エピ射・モノ射と全射単射は完全に一致する概念ではない。

3)全順序

最後は全順序である。
全順序集合は次の要件を満たすものである。
1) 反射律(reflexivity):任意の\(a \in P\)に対して、\(a \leq a\)である(この要件は全順序律に含まれるので省いてもよい。ここでは、要件を増やしながら説明しているので、そのまま載せておいた)。
2) 推移律(transitivity):任意の\(a,b,c \in P\)に対して、\(a \leq b\)かつ\(b \leq c\)であれば、\(a \leq c\)である。
3) 反対称律(asymmetry):任意の\(a,b \in P\)に対して、\(a \leq b\)かつ\(b \leq a\)であれば、\(a = b\)である。
4) 全順序律(totality):任意の\(a,b \in P\)に対して、\(a \leq b\)か\(b \leq a\)である。

このように、全ての二つの要素に対して\(\leq\)の関係がつけられるものを全順序と呼ぶ。

建物では、どの二つの階もどちらが高いか比較できるので全順序になっている。二つの階\(A,B\)に対して、\(A \leq B\)を\(A\)は\(B\)よりも高くはないということにすると、図の階\(A,B,C,D\)について、圏を作成すると以下のようになる。
f:id:bitterharvest:20161108104159p:plain

出来上がった圏は次のようになっている。
1) 対象:階\(A,B,C,D\)
2) 射:高低関係 \(f,g,h,u,v,w\),及び、恒等射と合成された射
3) ドメインとコドメイン: \(f:A \rightarrow B, g:B \rightarrow C, h:C \rightarrow D,... \)
4) 恒等射:\(id_A,id_B,id_C,id_D\)
5) 合成:\(u=g \circ f, \ v=h \circ g, \ w=h \circ g \circ f\)
① 結合律:\((h \circ g) \circ f = h \circ (g \circ f)\)であるので満足している。
② 単位律:\(f \circ id_A = f = id_B \circ f,...\)であるので満足している。

4.5 ホモトピー論からの圏

薄い圏が出てきたので、厚い圏(thick category)の例を挙げよう。二つの対象の間に複数の射があるものが厚い圏になるが、どのようなものがあるだろうか。

位相空間が出てきたので、それより、もっと近代的な数学の一分野であるホモトピー論に登場してもらおう。実は、ホモトピー論とコンピュータ科学の関係は、私事になるが、私の研究分野である。これまでにいくつかの論文を執筆してきた。当初は関心をあまり引かなかったようだが、最近では、少しずつではあるが、読んでくれる人が増えてきて喜んでいる。

ホモトピー論にまともに立ち向かうと大変なことになるので、その考え方が伝わるように図を多用して説明しよう。下の図は公園である。公園には池が二つある。それらは青色で示してある。
f:id:bitterharvest:20161108113141p:plain

ある人が黒い地点(ここでは基点と呼ぶことにしよう)にいるとしよう。そして、一回りして基点に戻ってくることにする。例えば、池を巡らない方法は、いくつか考えられるが、例えば、図で示したように赤色と黄色の路がある。
f:id:bitterharvest:20161108113256p:plain

二つの路(Path)は、連続的に変化したときに相手側に行くことができれば、同値な路ということにする。少し工夫すると赤色から黄色の路に連続的に変形して移れることが分かる。
f:id:bitterharvest:20161108113337p:plain

これから、池を巡ってこない路は全て同値ということになる。そこで、池を巡らない路を赤色の路で代表させることにする。

同じように考えると、左側の池を巡ってくる路はすべて同値になる。そこで、池をめぐる路の代表を茶色の路にしよう。
f:id:bitterharvest:20161108114636p:plain

さらに、右の池を巡ってくる路の代表を灰色の路としよう。
f:id:bitterharvest:20161108114733p:plain

これらの路は、お互いに連続な変形をして移ることができないので、独立であるという。この他に独立な路はないであろうか。二つの池をめぐる青色の路はどうであろうか。
f:id:bitterharvest:20161108120851p:plain

結論から言うと、青色の路は独立ではない。茶色の路を辿った後で灰色の路を辿ることで構成される合成された路を考えてみよう。この合成された路からは、下図に示すように、青色の路に連続的に変形できる路が存在する。従って、青色の路は独立とはならない。
f:id:bitterharvest:20161108121443p:plain

それでは、この公園でのホモトピー的な路を圏にしてみよう。図で示すと次のようになる。
f:id:bitterharvest:20161108130748p:plain
図において、池を巡らない赤色の路は恒等射となる。これは、赤色の路は縮めていくと基点と一致してしまう。これは、基点から動かないことと同じなので、恒等射となる。独立な茶色と灰色の路は、射となる。これらは\(f,g\)で表すことにする。また、赤色の路と灰色の路を何回かたどるのも基点から基点へ至る路であるので、\(f\)と\(g\)を合成したもの(何回用いてもよい)も射である。


1) 対象:基点\(X\)
2) 射:路 \(f, g, s,t,u,.., \)
3) ドメインとコドメイン: \(X\)
4) 恒等射:池を巡らない路(赤色の路)\(id_X\)
5) 合成:\(\circ\)(基点を軸にして何度も路を回る)
① 結合律:満足している(路の周りかたは、結合の仕方によらない)。
② 単位律:\(f \circ id_X = f = id_X \circ f,g \circ id_X = g = id_X \circ g\)であるので満足している。

路から作られる圏は、無数の射を有していることが分かる。これは、厚い圏の例である。

次の図はトーラスである。
f:id:bitterharvest:20161108134404p:plain
このトーラスと先ほどの公園とは全く違うものに見えるかもしれない。しかし、トーラスの一点を基点とし、そこで、路を考えてみよう。路の一つは、トーラスの穴に沿ってぐるりと回ってくるもの(図では\(f\))である。他の一つは、それとは直角方向にぐるりと回るもの(図では\(g\))である。恒等射となる路は、一周せずに戻ってくるもの(図では\(id_X\))である。他の路はこれらの合成により作られる。従って、トーラスと先ほどの公園は、同じ圏となる。トーラスは3次元で、公園は2次元であるにもかかわらず同じものとみなされる。何とも面白い世界をホモトピー論は扱う。

トーラスだけでなく、下図に示すカップクラインの壺も同じ圏になる。
f:id:bitterharvest:20161109071318p:plain

ホモトピー論の世界では基本群などを用いて物体の性質を表す。トーラスやクラインの壺の基本群は\({\mathbb Z} \times {\mathbb Z}\)である。\({\mathbb Z}\)は整数を表すが、ここでの意味は、回ってくる回数を表す。

公園の場合には、池の周りをまわる回数となる。逆回りの時は回数を減らすものと考える。従って、回数は、負を含むので、自然数ではなく整数となる。左の池と右の池を回ることは独立であったので、独立な回り方が二通りあるということで、\({\mathbb Z} \times {\mathbb Z}\)と表す。

最近のホットな数学の分野はホモトピー・タイプ論(homotopy type theory)である。この分野でタイプの研究が進むと、Haskellは多大な恩恵を受けるものと期待している。

集合から圏論へ:ミクロな世界からの宇宙への旅立ち(2)

3.2 集合の要素を射に

集合の世界は要素を中心に考えるが、圏論の世界は射を中心に考える。そこで、集合を考えるとき、その要素を射に変えるものが必要となる。
その役割を果たしてくれるのが、一つだけの要素からなる集合である。この集合はシングルトンと呼ばれる。Haskellではデータ型()として用意している。

確認してみよう。まず、()のデータ型を調べるてみよう。

Prelude> :i ()
data () = () 	-- Defined in ‘GHC.Tuple’
instance Bounded () -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’

instance Eq () -- Defined in ‘GHC.Classes’
instance Ord () -- Defined in ‘GHC.Classes’
instance Read () -- Defined in ‘GHC.Read’
instance Show () -- Defined in ‘GHC.Show’
instance Monoid () -- Defined in ‘GHC.Base’

ちなみに、\(Int\)と\(Bool\)のデータ型を調べると次のようになっている。

Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# 	-- Defined in ‘GHC.Types’
instance Bounded Int -- Defined in ‘GHC.Enum’
instance Enum Int -- Defined in ‘GHC.Enum’
instance Eq Int -- Defined in ‘GHC.Classes’
instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Ord Int -- Defined in ‘GHC.Classes’
instance Read Int -- Defined in ‘GHC.Read’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
Prelude> :i Bool
data Bool = False | True 	-- Defined in ‘GHC.Types’
instance Bounded Bool -- Defined in ‘GHC.Enum’
instance Enum Bool -- Defined in ‘GHC.Enum’
instance Eq Bool -- Defined in ‘GHC.Classes’
instance Ord Bool -- Defined in ‘GHC.Classes’
instance Read Bool -- Defined in ‘GHC.Read・f
instance Show Bool -- Defined in ‘GHC.Show’

データ型\(Bool\)は\(data \ Bool = False | True\)となっているので、\(False\)と\(True\)二つの要素を取ることが分かる。また、\(Int\)については、その要素はGHC.Typesで定義されていることが分かる。
遡って、シングルトンは、\(Data () = ()\)となっていたので、要素も()であることが分かる。確認してみよう。

Prelude> :t ()
() :: ()

である。::の左側は要素の()で、右側はデータ型の()である。

シングルトンを用いると、集合の要素を射に変えることができる。それは、シングルトンから集合の要素\(a\)へ向かう矢印\(f_a\)を用意することで実現できる。下図は、自然数の集合の各要素を射で表したものである。この場合、射の数は無数になる(但し、数え上げることはできる)。
f:id:bitterharvest:20161105091506p:plain

シングルトンは要素の数が一つだけの集合である。それでは、要素の数がゼロの集合はあるのだろうか。これは、数の議論に似ている。建物で、地面に接している階を、日本では1階にしているが、海外に行くと0階(あるいはGround)となっていることに戸惑った人は多いことだろう。普段の癖で思わず1階のボタンを押してしまい、エレベータのドアーが空いたときそこがロビーでないことにビックリした経験を誰しも持っているのではないだろうか。

数学の世界では、要素の数がゼロの集合が存在する。これは空集合と呼ばれる。前の記事で述べたが、Haskellの世界では\(Void\)として用意している(但し、これを用いるときは、Data.Voidというモジュールをインポートする必要がある)。それでは確認してみよう。

Prelude> import Data.Void
Prelude Data.Void> :i Void
data Void 	-- Defined in ‘Data.Void’
instance [safe] Eq Void -- Defined in ‘Data.Void’
instance [safe] Ord Void -- Defined in ‘Data.Void’
instance [safe] Read Void -- Defined in ‘Data.Void’
instance [safe] Show Void -- Defined in ‘Data.Void’

\(Void\)と呼ばれるデータ型があることが分かる。

\(Void\)は要素が何もないので、真空の状態と見なすことができる。宇宙が真空の状態から埋めれたように、空から有が生じると考えることができる。あるいは、論理の世界では、\(Void\)は偽(\(false\))、シングルトンは真(\(true\))と見なす。論理の世界では、嘘の上にどのようなことを述べたとしても正しいと考えるので、偽からはどのような事でも生みだせると考える(ここでは生み出すものはデータ型)。その役割をしているのが\(absurd\)という関数である。確認してみよう。

Prelude Data.Void> :t absurd
absurd :: Void -> a

\(absurd\)という関数は、任意のデータ型を出力していることが確認できた。\(absurd\)の意味は、常識に反した、理屈に反する、非条理ななどだ。このようなわけで、この関数は用意してあるだけで使うことはまずない。ここでは、それぞれのデータ型はこれから生み出されたと考えておくことにしよう。

要素の数が0と1の集合について話したので、ついでに要素数が2である集合は何であろうか。勿論、偽と真の値を有するブール集合である。Haskellではデータ型\(Bool\)として用意しているが、有用性が高いことは言うまでもない。