bitterharvest’s diary

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

日の名残り―The remains of the day

今日、紹介する映画は、『日の名残り』(The Remains of the day)だ。今年度のノーベル文学賞に輝いたカズオ・イシグロの同名の小説を映画化したものだ。1993年の作品で、アカデミー賞の8部門にノミネートされたが、残念ながら、受賞には至らなかった。ちなみに、この年の作品賞には『シンドラーのリスト』が選ばれた。小説としての『日の名残り』は、1989年に発表され、同年にブッカー賞を受賞している。

ストイックともいえるほどに職務に忠実な執事の日常生活を淡々と描いた作品で、アンソニー・ホプキンズがその役を演ずる。

古いタイプの人間を描いたと言えばそれまでなのだろうが、新しく雇った女中頭のケントン(エマ・トンプソンが演じる)に淡い恋心を抱きながらも、ケントンが誘い掛けてくる言葉にも、執事としての対応しかできない、不器用な初老の執事スティーブンスの物語である。

日本には「道」というのがある。武士道、茶道、華道などだ。一つのことを究めようとする精進がそれぞれで問われる。ホプキンズが演じる執事も、執事としての道に精進しているのであろう。昨年、一流大学を卒業し、有名な航空会社で実績を上げていたにもかかわらず、禅僧となった方に、鎌倉の円覚寺を案内してもらう機会があった。境内を案内してくれる道すがら、禅僧はなぜお坊さんになったのか、僧になるための修業はどのようなものだったのかを語ってくれた。禅の道を究めようとする姿が、執事の姿と重なった瞬間、この映画がさらに好きになった。

作品の内容については映画の方を見て欲しいが、好意に感謝しながらも、それを素直に表現できない無骨さが表れている部分を紹介しよう。

スティーブンスが執事をしている貴族の館でキツネ狩りをする場面がある。
f:id:bitterharvest:20171021102123j:plain

このとき、女中頭として働くことになるケントンは、面接試験を受けに来る。
f:id:bitterharvest:20171021101619j:plain
f:id:bitterharvest:20171021101644j:plain

無事面接に合格したケントンは仕事を始める。スティーブンスの殺風景な個室を明るくしようと考えて、庭先の綺麗な花を摘む。
f:id:bitterharvest:20171021101828j:plain

そして、執務室を訪れ、花を飾りながら、次のように言う。
"I thought these might brighten your parlour."
f:id:bitterharvest:20171021102549j:plain

現在のことを言っているのに、過去形が使われている。高校時代に習った「仮定法過去」という文法の用語を思い出す人もいるだろう。

日本でも、ファーストフード店などに行くと過去形で応対されることがある。慣れていないと面食らってしまう。先日も、オーダーが済んだ後の確認で、「ご注文は以上でよろしかったですか」と言われた。

丁寧さを表すために過去形を用いている。日本語には丁寧語、謙譲語、尊敬語が備わっているので、お客さんとの対応にはこれらの言葉を使えばよい。しかし、ファーストフード店のように仕事を定型化したいところでは、状況に合わせての対応を嫌う。そこで、マニュアル化するために、何とも不思議な言い回しが生まれたのだろう。

英語では、可能性が含まれるような状況を述べるときは、ファーストフード店のような言い回しが普通だ。ケントンがスティーブンスに向かって、「この花が部屋を明るくしてくれますよ。」というのは、あまりにもフランクすぎる。時代は戦前のイギリスで、場面は貴族の館であれば、かつての日本語ではないが、状況に応じた適切な表現が要求される。

mightにはいくつかの使い方があるので、Collinsの"English Grammar"で確認した。4章の「ありそうなことを示唆する」という項目の中の4.137に、可能性として使われる'could','might','may'というのがある。これらの単語は「あることが生じる可能性があるときに」用いると説明がある。例文には、
They might be able to remember what he said.
というのがある。

これらを踏まえると、上の訳は
「お花が執務室を明るくしてくれたらと思ってお持ちしました。」
でどうだろうか。

ケントンの思いがけない行為に面食らって、スティーブンスは次のように言う。
"Beg your pardon?"
この言い回しも、思い出の深い言い回しだ。留学して初めてホームステイをした時、アメリカ人の夫婦の会話の中でしょっちゅう"I beg your pardon."というのを聞いた。日本だと相手の言っていることを聞き直すのは失礼だと考えて、少し前にはやった「忖度をして」、行動しがちだが、彼らは、意味を取り違えないように頻繁に確認を取っていたのがとても印象的だった。

ここは、
「何て言われましたか?」
だろうか。

ケントンは少し表現を変えて、温かみを持たせて次のように言う。
"They might cheer things up for you."
「お花が、周りのものを生き生きとさせてくれ、あなたも明るく仕事ができるのではと思いまして。」

スティーブンスはありきたりな表現で、
"That's very kind of you."
「ご親切に、どうもありがとう。」

ケントンは、スティーブンスの意図を解さないのか、提案を示す"If you like"と"could"(Collins 4.187)を用いて
"If you like, I could bring in some more for you."
「よろしければ、もっとお持ちします。」

スティーブンスは自分のプライベートな生活に入り込まれることを嫌って、
"Thank you, but I regard this room as my private place of work and I prefer to keep distractions to a minimum."
「そのように気を使って下さってありがとう。しかし、この執務室は仕事をするための私の個人的な場所なので、気を紛らわすようなことは最小限にしたいと心がけていますので。」

ケントンは思いがけないことを言われたので、少し攻撃的になって、丁寧を表す"would"を使うが内容は強い表現で、
"Would you call flowers a distraction, then?"
「この花が気晴らしだというの。」

スティーブンスは、いなして、
"I appreciate your kindness. I prefer to keep things as they are."
「あなたのご親切には感謝しています。でも、このままの方がいいのです。」

この後、スティーブンスは父親の呼び方について注意する。ケントンは再びカチンとくる。その場面の表現も面白いので、映画で確認してください。

プログラマーのための圏論(下)

プログラマのための圏論』は(上・中)の後の部分をまとめ(下)にしてPDFファイルにしました。参考にしてください。なお、(上)のホームページはこちら
(中)のホームページはこちら

モナドの応用

最後に

ノーベル経済学賞を受賞したダニエル・カーネマン教授が一般読者向けに著述した『ファスト&スロー』を読んだ。本のタイトルからは内容はつかみにくい。副題は「あなたの意志はどのように決まるか?」となっているので、脳科学の本かなと思い違いしてしまいそうだ。英語でのタイトルは、”Thinking, Fast and Slow”となっているので、彼の研究内容をある程度知っている人でない限り、タイトルから内容を読み取ることはやはり難しい。
f:id:bitterharvest:20171012200712j:plain
先週はノーベル賞が発表される時期であったため、カーネマン教授の名前を思い出した人も多いことと思う。特に、今年(2017年)のノーベル経済学者はリチャード・セイラー教授だったので、その関連でカーネマン教授を思い出した人は多いだろう。二人とも行動経済学に大きな貢献をしたことでノーベル賞を受賞している。伝統的な経済学は、経済活動をする人たちが経済合理性を備えているということを前提に、理論を構築していた。これに対し、カーネマン、セイラー両教授とも、人間は合理的にふるまうことはまれで、様々なバイアスがかかって行動することを前提に、新しい経済学の理論を構築した。

経済学賞のため、カーネマン教授は生粋の経済学者だと思いがちだがそうではない。カリフォルニア大学バークレー校で1961年に心理学の博士号を取得し、その後、同大学やプリンストン大学で心理学の教授となっている。心理学と経済学を融合し、独自のプロスペクト理論を確立して、人間の経済的行動を説明し、ノーベル賞を受賞するに至っている。

『ファスト&スロー』では、二つの架空のキャラクター、二つの人種、二つの自己を用いて、一人の人間がどのように意思を決定するかを説明している。一つのものが二つの性格を持つということは、圏論の「モナドだ」に相当するものだと思って、この本を読んでいくととても面白い。

『ファスト&スロー』の結論の部分に、それぞれの性格が記述されているので引用してみよう。「二つのキャラクターとは、早い思考をする直感的なシステム1と遅い思考をする熟考型のシステム2であるシステム2はシステム1の監視を引き受け、限られたリソースの中でできる限りの制御を行う。二つの人種とは、理論の世界に住む架空の人種エコンと、現実の世界で行動するヒューマンである。二つの自己とは、現実を生きる「経験する自己」と、記憶を取り選択する「記憶する自己」である」と言っている。

システム1と2は、「XXが自動的に起きた」ということを「システム1がXXした」と、「興奮度が高まり、同行が開き、注意力が集中してXXが行われた」ということを「システム2が呼び出してXXが行われた」と言うように、分かりやすく説明するために使われた架空のものである。将棋の藤井4段が、複数人のアマを相手に将棋を指しているときは、システム1を用いてヒューリスティックに駒を置いている。それに対して、トップ棋士と対戦しているときは、システム2を用いて、アルゴリズムをフルに機能させて、勝利へ導く手順を探している。

二つの人種では、エコンは経済合理性に従って行動する自分である。それに対して、現在置かれている環境に影響されて、経済合理性には適わない行動をとるのがヒューマンである。例えば、大きな負債を抱えているときに、それを取り返すために起死回生を狙って大博打をし、結局、損をするのがヒューマンである。

ロマンスの破局は、振る側と振られる側に分かれる。どちらもわかれという面では変わらないのに、精神的なダメージは振られる側が大きい。「逃がした魚は大きい」という喩えもあるがこれも同じようなものだ。もし、ロマンスの期間を細分して、それぞれの時点での幸福度を記憶していたとすれば、振った側も振られた側もそれほど変わらないだろう。しかし、このようなことは忘れてしまい、破局の瞬間だけが記憶に残るようだとすると、振った側と振られた側の衝撃には大きな差がある。「終わりよければ全てよし」という諺があるが、これも同じようなことを伝えている。

モナドとこれらの関係を図で示すと図のようになる。
f:id:bitterharvest:20171012194340p:plain

モナドの世界では、\(A\)の世界を純粋な世界と解釈し、\(M(A\)の世界を現実の世界と見なした。これをカーネマン教授のモデルと対応させると、純粋な世界\(A\)はシステム2、エコン、記憶する自己に相当し、現実の世界\(M(A)\)はシステム1、ヒューマン、経験する自己に相当する。とても理にかなった対応で面白いと思う。このように、全く関係なかったと思われる世界がつながるとき、とても嬉しくなる。

圏論Haskellも奥の深い学問分野である。圏論だけで理解することも難しいし、Haskellだけで理解することも難しい。しかし、両方を一緒に勉強することで、理論と実践の両面を同時に見ることができるようになる。これによって、両方の分野をより正確に知ることができる。このブログでは、図やプログラムをたくさん掲載し、可視的に、具体的に理解できるように試みた。

今回の記事で、「プログラマのための圏論」はひとまず終了である。お付き合いいただきありがとうございました。

モノイドーモノイド圏での記述

13.4 モノイド圏での記述

二項演算子は双関手として下図に示すように表すことができる。
f:id:bitterharvest:20171007172504p:plain

双関手のクラスはHaskellでは次のように定義されている。

class Bifunctor p where
  bimap :: (a -> b) -> (c -> d) -> p a c -> p b d

上の定義で、二項演算子を\(\otimes\)と表すならば、\(p\)は\((\otimes)\)と書き直してもよい。

そこで、\(bimap\)の対象を自己関手で置き換えと、次のように表すことができる。
\(bimap :: (F \rightarrow F') \rightarrow (G \rightarrow G') \rightarrow (G \circ F \rightarrow F' \circ G') \)
上の定義で、\((F \rightarrow F'),(G \rightarrow G'),(G \circ F \rightarrow F' \circ G') \)は自然変換で、\(\circ\)は関手の合成で、\(\otimes\)と見なせるものである。上の式を互換図で表すと、以下のようになる。
f:id:bitterharvest:20171007174754p:plain

ところで、モノイドの定義はHaskellでは次のようになっていた。

class Monoid m where
  mu :: m -> m ->  m
  eta :: () -> m

上のプログラムを同じように自己関手(ここでは\(T\)としておく)で置き換えると、
\(\mu :: T -> T ->T \)
 \eta :: Id -> T
と表すことができる。

これを互換図で示すと下記のようになる。
f:id:bitterharvest:20171008082200p:plain

前の記事で、乗算を行うモノイド\(Pfunctor\)に対して、次のようにカテゴリー圏を用意した。

module Pfunctor (Product, Pfunctor, Category) where

newtype Product n = Product n deriving (Eq, Ord, Read, Show)

instance Functor Product where
  fmap f (Product x) = Product (f x)
  
join (Product (Product x)) = Product x

newtype Pfunctor x y = Pfunctor {runPfunctor :: x -> Product y}

class Category cat where
  id :: cat a a
  (.) :: cat b c -> cat a b -> cat a c

instance Category Pfunctor where
  id = Pfunctor (\x -> Product x)
  (Pfunctor f) . (Pfunctor g) = Pfunctor $ join Prelude.. fmap f Prelude.. g

それでは、\(Pfunctor\)をクラス\(Monoid\)のインスタンスとして定義しよう。
HaskellのPreludeでは、\(Monoid\)は\(mempty,mappend\)を用いて定義されているが、ここでは前々回の記事で紹介したように、 \eta,\(\mu\)を用いることにしよう。

class Monoid' m where
  mu :: m -> m ->  m
  eta :: () -> m

instance Monoid' (Pfunctor x x) where
  eta () = Pfunctor (\x -> Product x)
  mu f g = Pfunctor (\x -> runPfunctor (f Pfunctor.. g) x) 

上のインスタンスの定義の中で、関手\(f,g\)は、\(f=g\)であり、\(f \circ f=f\) を満たさなければならない。

そこで、\(mu\)を直接使うのではなく、同一の関手を使うようにするため、次の\(mu'\)を用意する。

mu' f =  mu f f

また、\(f \circ f=f\)であることを確認するために、\(f \circ f\)と\(f\)で同じ値が得られるかをチェックし、同じであれば出力し、違っていれば出力しないようにしよう。そのために次の関数\(getResult\)を用意する。

\(n\)で割った時の剰余と、絶対値を出力する関手\(modular,abosolute\)を次のように用意しよう。これは、\(T \circ T = T\)の条件を満たしている。

modular :: (Integral y) => y -> Pfunctor y y
modular n = Pfunctor (\x -> Product (mod x n))

absolute :: Pfunctor Integer Integer
absolute = Pfunctor (\x -> Product (abs x))

それではこれを用いて、二つの数\(x,y\)を入力し、\(F x \otimes F y\)を求めてみよう。

*Pfunctor> getResult (modular 5) (34, 67)
Just (Product 3)
*Pfunctor> getResult absolute (12, (-9))
Just (Product 108)

最初の実行例は、入力34,67の5の剰余を求め、その乗算を行うものだ。34の剰余は4であり、67の剰余は2である。従って、4と2の乗算結果は8であるが、これも5の剰余での乗算を行うので、結果は\(Product \ 3\)である。正しい答えであることが分かる。前回の記事で紹介した\(otimes\)を用いると\(Product \ 8\)が得られる。剰余としての掛け算が配慮されていないことが分かるので用いるのには不備がある。

ところで、前回の記事で用いた\(times\)を使うとどのようになるかを見てみよう。もちろん、この関手は\(T \circ T = T\)を満たしていない。

*Pfunctor> getResult (times 3) (4, 5)
Nothing

予想通りである。従って、\(times \ n\)はモノイドのメンバーでないことが分かる。

13.4 モノイド圏

それでは、モノイド圏をまとめよう。
1) 対象:関手の集まり\(M=\{F, G, H,...\}\)。但し、\(F \circ F=F,G \circ G=G,H \circ H=H...\)である。
2) 射:自然変換\(\mu\)
3) ドメイン・コドメイン
4) 恒等射:自然変換\(\mu\)
5) 合成:\(\circ\)

モノイド圏が結合律、単位律を満たしていることを互換図で確認してみよう。ここでは、\(T \circ T\)を\(T^2\)で表す。
f:id:bitterharvest:20171008100802p:plain

13.4 モナドはモノイド?

この圏の定義も、結合律、単位律の互換図もどこかで見たことはないだろうか。そう、モナドを説明した記事と同じものだ。このことから次のことがいえる。

モナドは、自己関手のカテゴリー圏で記述されたモノイドと同じ」と言える。

これは重要な定理である。

最後の用いたプログラムのリストをつけておこう。

instance Functor Product where
  fmap f (Product x) = Product (f x)
  
join (Product (Product x)) = Product x

newtype Pfunctor x y = Pfunctor {runPfunctor :: x -> Product y}

class Category cat where
  id :: cat a a
  (.) :: cat b c -> cat a b -> cat a c

instance Category Pfunctor where
  id = Pfunctor (\x -> Product x)
  (Pfunctor f) . (Pfunctor g) = Pfunctor $ join Prelude.. fmap f Prelude.. g

times :: Num y => y -> Pfunctor y y
times n = Pfunctor (\x -> Product (n * x)) 

adds :: Num y => y -> Pfunctor y y
adds n = Pfunctor (\x -> Product (n + x)) 

otimes :: (Num n) => (Pfunctor a n, Pfunctor a n) -> (a, a) -> Product n
otimes (Pfunctor f, Pfunctor g) (x, y) = Product c 
  where 
    Product a = runPfunctor (Pfunctor f) x
    Product b = runPfunctor (Pfunctor g) y
    c = a * b

class Bifunctor p where
  bimap :: (a -> b) -> (c -> d) -> (p a c -> p b d)

class Monoid m where
  mu :: m -> m ->  m
  eta :: () -> m

instance Pfunctor.Monoid (Pfunctor x x) where
  eta () = Pfunctor (\x -> Product x)
  mu f g = Pfunctor (\x -> runPfunctor (f Pfunctor.. g) x) 
  
mu' :: Pfunctor n n -> Pfunctor n n
mu' f = mu f f

getResult f (x,y)
  | a == b = Just a
  | otherwise = Nothing
  where
    a = runPfunctor (mu' f) (x*y)
    b = runPfunctor f (x*y)

modular :: (Integral y) => y -> Pfunctor y y
modular n = Pfunctor (\x -> Product (mod x n))

absolute :: Pfunctor Integer Integer
absolute = Pfunctor (\x -> Product (abs x))

モノイドーカテゴリー圏での記述

13.3 カテゴリー圏での記述

これまで、算数で最初に学んだ加算・乗算に代表されるモノイドと呼ばれる二項演算を、圏論でどのように記述したらよいのかについて話を進めてきた。即ち、アセンブラ言語でのように処理を具体的に記述するのではなく、高級言語でのように物事がどのように成り立っているかを構成的に記述しようと試みてきた。これは、モノイドのそれぞれについて具体的に個別に記述を進めるのではなく、モノイドと呼ばれるものが有している性格を抽象的に汎用的に進めようとするアプローチである。前者が技法的なアプローチであるのに対して、後者は科学的なアプローチでもある。

構成を記述する圏論では、構成図を利用することで可視的に計算の概念を示すことができる。モノイドがどのように構成されているのかについて説明するときも、式を展開していくよりは、構成図がどのように変化していくかを示すことで、書き手にとっても、読み手にとても、理解しやすくなる。そこで、ここでは、構成図をうまく利用して、分かりやすい形で求めてみよう。

集合から射へ

前回の記事で、モノイドの例を一つ紹介した。下図での左側がそれである。

f:id:bitterharvest:20171005093645p:plain

ここでは、代数学での記述法に従って、集合\(S=\{0,1,2-\sqrt{3},2+\sqrt{3}\}\)、単位元1、二項演算子\(*\)と表されているものを、圏論での記述に従って、左側の構成図で表した。この図は圏の構成を満たしている。即ち、
1)対象が星
2)射が\(\{0,1,2-\sqrt{3},2+\sqrt{3}\}\)
3)ドメインとコドメインが星
4)恒等射が1
5)合成が\(\times\)
であることを表している。また、単位律、結合律は満たされている。

上図の右側は、対象がモノイドであることを、明確にしたものである。数としての\(0,1,2-\sqrt{3},2+\sqrt{3}\)は加減乗除を始めとする様々な二項演算に使われる。そこで、これらが、乗算で用いられることを明確にするために、\(Product\)と呼ばれるコンテナを付与した。右側も、左側と同様に圏であることに注意しよう。このため、圏\(\mathcal{A}\)と圏\(\mathcal{B}\)は関手\(Product::\mathcal{A} \rightarrow \mathcal{B}\)によって結ばれていると見ることができる。

集合の構成要素を一般化して、上図を少しだけ抽象化すると下図を得る。何となく圏論らしくなってきたのが分かるだろう。
f:id:bitterharvest:20171005101640p:plain

右側の圏は、
1)対象が星
2)射が\(\{M(f),M(g),...\}\)
3)ドメインとコドメインが星
4)恒等射が\(id_B=M(id_A)\)
5)合成が\(\circ\)
である。また、単位律、結合律は満たしている。

ここまでの変換で、代数学で集合として表されていたものが、圏では射の集合として表されていることが分かる。でも、集合であることには変わりはない。

カテゴリー圏へ

それでは、圏\(\mathcal{A}\)と圏\(\mathcal{B}=M(\mathcal{A})\)を対象とし、その間を関手\(M\)で結合するような圏\(\mathcal{C}\)を下図のように構成してみよう。
f:id:bitterharvest:20171007061902p:plain

\(\mathcal{C}\)において、\(\mathcal{B}\)から同じように関手\(M\)で\(M(\mathcal{B})\)に接続しよう。これをさらに行うと、\(\mathcal{C}\)は無限に関手\(M\)で結合された圏となる。ところで、原点に立ち戻って、\(Product\)で考えると、\(Product (Product (x))\)は、\(x\)を乗算ができる世界へと持ち込んだ。これが、\(Product(x)\)である。これをもう一度乗算ができる世界へ持ち込むと\(Product (Product (x))\)となるが、元々、乗算ができる世界に存在しているので、\(Product (Product (x))=Product(x)\)となる。

そこで、二項演算ができる世界に持ち込む関手\(M\)については、\(M(M(\mathcal{A})) = M(\mathcal{A})\)と見なすことができるので、\(\mathcal{C}\)は下図のようになる。
f:id:bitterharvest:20171007063355p:plain

ここで、\(\mathcal{A}\)と\(\mathcal{B}=M(\mathcal{A})\)の構造は考慮しなくてよくなるので、上図は以下のように書き表すことができる。ここで、念願の集合を取り除くことができ、アセンブラの世界から高級言語の世界へと入ることができた。
f:id:bitterharvest:20171007063557p:plain

圏\(\mathcal{C}\)の対象は\(\mathcal{A}\)と\(\mathcal{B}=M(\mathcal{A})\)であり、射は\(M\)である。それでは、この圏での恒等射と結合を求めてみよう。

\(M\)はこれまで関手と言ってきたが正確に記述すれば関手の集まりである。即ち、\(M=\{Id,F,G,...\}\)である。ここで、\(Id\)は恒等射である。恒等射と合成を図で表すと次のようになる。
f:id:bitterharvest:20171007063913p:plain

圏\(\mathcal{C}\)の射は、関手である。これには、先に説明したように\(Id,F,G,...\)が含まれる。また、これには、合成により作られたもの、例えば、\(F \circ G\)なども含まれる。射だけを表すと下図になる。
f:id:bitterharvest:20171007065700p:plain

圏と圏を関手でつないで作成した件をカテゴリー圏と呼ぶが、モノイドをカテゴリー圏で表すと以下のようになる。

1) 対象:圏の集まり\(\mathcal{C}=\{\mathcal{A},M(\mathcal{A})\}\)
2) 射:関手の集まり\(M=\{Id,F,G,...\}\)
3) ドメイン・コドメイン:\(\{Id :: * \rightarrow M(*), F :: * \rightarrow M(*), G :: * \rightarrow M(*)... \}\)。ここで、*は\(\mathcal{A}\)または\(M(\mathcal{A})\)である。さらに、\(M(M(A))=M(A)\)である。
4) 恒等射:\(Id\)
5) 合成:\(\circ \)

結合律、単位律を満たさなければならない。

Haskellでの記述

モノイドをカテゴリー圏で表すことができたので、これをHaskellのプログラムで表すことにしよう。

ここで作るプログラムは、乗算を演算子として持つモノイドである。

\(\mathcal{A}\)を\(n\)とし、\(M(\mathcal{A})\)を\(Product \ n\)とした時に、前と同じように、\(new type\)を用いて\(Product \ n\)を用意しよう。

newtype Product n = Product n deriving (Eq, Ord, Read, Show)

\(Product\)は\(n\)から\(Product \ n\)を導き出す関手である(カテゴリー圏を説明したときの\(M\)に相当)。そこで、これを\(Functor\)のインスタンスとして定義する。さらに\(Product (Product \ n)=Product \ n\)を満たすので、これを\(join\)という関数で定義しておこう。

instance Functor Product where
  fmap f (Product x) = Product (f x)
  
join (Product (Product x)) = Product x

さて、次にカテゴリー圏を作る作業に移ろう。\(M=\{Id,F,G,...\}\)であったので、これを表すようなデータ型を用意しよう。その名前を\(Pfunctor \ x \ y\)とする。ここで、\(Pfunctor\)は、\(x\)を入力、\(y\)を出力とする関数である。また、この関数からの出力を得られるように\(run Pfunctor\)を用意しておこう。

newtype Pfunctor x y = Pfunctor {runPfunctor :: x -> Product y}

また、カテゴリー圏のクラスは次のように定義する。ここでは、恒等射と結合の関数を定義することにする。

class Category cat where
  id :: cat a a
  (.) :: cat b c -> cat a b -> cat a c

\(Pfunctor\)をカテゴリー圏のインスタンスにしよう。

instance Category Pfunctor where
  id = Pfunctor (\x -> Product x)
  (Pfunctor f) . (Pfunctor g) = Pfunctor $ join Prelude.. fmap f Prelude.. g

上のプログラムで、\((Pfunctor f)\)と、\((Pfunctor g)\)のところに、\(F\)や\(G\)の関手が来る。

これを用意しよう。一つは、\(x\)を\(n\)倍した\(Product \ n*x\)を作り出す関手\(times\)である。

times :: Num y => y -> Pfunctor y y
times n = Pfunctor (\x -> Product (n * x)) 

他の一つは、\(x\)を\(n\)だけ加算した\(Product \ n+x\)を作り出す関手\(adds\)である。

adds :: Num y => y -> Pfunctor y y
adds n = Pfunctor (\x -> Product (n + x)) 

ここまでのプログラムをモジュール\(Pfunctor\)にして一つにまとめよう。

module Pfunctor (Product, Pfunctor, Category, times, adds )where

newtype Product n = Product n deriving (Eq, Ord, Read, Show)

instance Functor Product where
  fmap f (Product x) = Product (f x)
  
join (Product (Product x)) = Product x

newtype Pfunctor x y = Pfunctor {runPfunctor :: x -> Product y}

class Category cat where
  id :: cat a a
  (.) :: cat b c -> cat a b -> cat a c

instance Category Pfunctor where
  id = Pfunctor (\x -> Product x)
  (Pfunctor f) . (Pfunctor g) = Pfunctor $ join Prelude.. fmap f Prelude.. g

times :: Num y => y -> Pfunctor y y
times n = Pfunctor (\x -> Product (n * x)) 

adds :: Num y => y -> Pfunctor y y
adds n = Pfunctor (\x -> Product (n + x)) 

それでは、これを利用してみよう。

最初に恒等射を利用してみよう。以下の実行例では恒等射を\(a\)にし、入力をいろいろに変えて出力を得ている。入力に\(Product\)がつくようであれば正しい。

Prelude> :load "Category.hs"
[1 of 1] Compiling Pfunctor         ( Category.hs, interpreted )
Ok, modules loaded: Pfunctor.
*Pfunctor> a = Pfunctor.id :: Pfunctor x x
*Pfunctor> runPfunctor a 3
Product 3
*Pfunctor> runPfunctor a 7.8
Product 7.8

大丈夫そうなので、\(times\)を利用して関手を作成し、それを実行してみよう。\(n\)倍になっている数が得られるか確認しよう。

*Pfunctor> b=times 3
*Pfunctor> runPfunctor b 4
Product 12
*Pfunctor> runPfunctor b 4.5
Product 13.5
*Pfunctor> c=times 9.8
*Pfunctor> runPfunctor c 4
Product 39.2
*Pfunctor> runPfunctor c 4.5
Product 44.1

正しそうなので、関手を合成してみよう。\(Product \ 3*(4+x)\)を求める合成関数を用意して計算してみよう。

*Pfunctor> d = times 3 Pfunctor.. adds 4
*Pfunctor> runPfunctor d 4
Product 24

単位律が満たされていることも確認しておこう。

*Pfunctor> a = Pfunctor.id :: Pfunctor x x
*Pfunctor> runPfunctor a 4
Product 4
*Pfunctor> d = a Pfunctor.. a
*Pfunctor> runPfunctor d 4
Product 4
*Pfunctor> b=times 3
*Pfunctor> runPfunctor b 4
Product 12
*Pfunctor> e = a Pfunctor.. b
*Pfunctor> runPfunctor e 4
Product 12
*Pfunctor> f = b Pfunctor.. a
*Pfunctor> runPfunctor f 4
Product 12

ついでに、結合律が満足されていることも確認しよう。

*Pfunctor> b=times 3
*Pfunctor> c = adds 5
*Pfunctor> e = (b Pfunctor.. c) Pfunctor.. b
*Pfunctor> f = b Pfunctor.. (c Pfunctor.. b)
*Pfunctor> runPfunctor e 4
Product 51
*Pfunctor> runPfunctor f 4
Product 51

モノイドの計算

それではモノイドでの計算を行ってみよう。モノイドは、\(M(\mathcal{A}) \otimes M(\mathcal{A}) \rightarrow M(\mathcal{A})\)である(二項演算子の中で最も一般的なものはテンソル積\(\otimes\)である。そこで、ここでは\(\otimes\)を用いて表すことにする)。従って、二つの関手を対\((Pfunctor a n, Pfunctor a n)\)で入力し、それぞれの関手への入力を対\((x,y)\)で入力するようにすると次のように定義できる。

otimes :: (Num n) => (Pfunctor a n, Pfunctor a n) -> (a, a) -> Product n
otimes (Pfunctor f, Pfunctor g) (x, y) = Product c 
  where 
    Product a = runPfunctor (Pfunctor f) x
    Product b = runPfunctor (Pfunctor g) y
    c = a * b 

簡単な例から実行しよう。二つの関手が恒等射であった場合には、入力データの積に\(Product\)がついたものとなる。以下は入力データが4と5なので、出力は\(Product 20\)となる。

*Pfunctor> a = Pfunctor.id :: Pfunctor x x
*Pfunctor> otimes (a,a) (4,5)
Product 20

関手\(times, adds\)も使ってみよう。以下の例は、最初の入力を3倍し、最後の入力を4加え、それらの積を求めたものである。

*Pfunctor> b=times 3
*Pfunctor> c=adds 4
*Pfunctor> otimes (b,c) (4,5)
Product 108

随分と抽象化が進んだが、次はさらに進めてみよう。

モノイドー代数学から圏論へ

13.2 代数学から圏論

モノイドになれたところで、モノイドを代数学での定義から始めて圏論での定義へと段々に抽象化してみよう。丁度、プログラミングで、アセンブリ言語での記述から高級言語での記述に変えていくことに相当する。

1) 代数学での定義

代数学では、モノイドは単位元のある半群と定義される。半群が分からないとこの定義は何だかわからないが、次のように定義しなおすことができる。

[代数学でのモノイドの定義]

モノイドは次の二つの条件を満たすものである。なお、最初の条件を満たすものを半群という。

1) 集合を\(S\)とし、そのうえで定義されている二項演算子を\(\times\)とする。このとき、集合\(S\)の任意の元を\(x,y\)とした時、\(z=x \times y\)となる元\(z \in S\)が存在し、また、任意の元\(x',y',z' \in S\)に対して、結合律\((x'\times y') \times z'=x' \times (y' \times z')\)が成り立つ。

2) 単位元\(e \in S\)を有し、任意の元\(x \in S\)に対して単位律\(e \times x = x = x \times e\)が成り立つ。

[モノイドの例]

それでは、モノイドの例を挙げてみよう。

集合を\(S = \{1, 0, 2+\sqrt{3}, 2-\sqrt{3}\}\)とし、二項演算子を乗算とすると、この集合は1を単位元とするモノイドである。

数学で集合を用いることは、プログラミングでアセンブリ言語を用いることに相当する。ここから逃げ出したい。

2) 構成図での定義

圏論を学び始めると、モノイドの構成図が出てくる。最初は戸惑うのだが、集合の要素を射とし、二項演算子を射の合成としたものである。上の例は次のように表される。
f:id:bitterharvest:20170929080923p:plain

これも、射の集合(Hom-Set)なので、やはり、集合から抜け出たい気分だ。

3) デカルト積での定義

デカルト積は二つの集合\(A,B\)のそれぞれから任意の元\(a \in A,b \in B\)を取り出す。\(a, b\)を元とする新たな集合\(A \times B\)を作り出す。即ち、

\begin{eqnarray}
A \times B = \{(a,b) | a \in A \land b \in B\}
\end{eqnarray}
である。

デカルト積を用いて、モノイドを定義しよう。ここでは、新たに、\(\mu\)と \etaという関数を用いて定義し、少し抽象度を上げる。

[デカルト積を用いての定義]

1) 二項演算:任意の\( (x, y) \in S \times S\)に対して\(\mu (x,y) = z\)となるような\(z \in S\)が存在する。
2) 単位元:シングルトン集合(要素のない集合)\(\ () \)に対して \eta()=eとなる。なお、\(e\)は\(S\)での単位元である。

結合律:任意の元\( (x, y, z) \in S \times S\)に対して、\(\mu(\mu(x,y),z)=\mu(x, \mu(y,z))\)が成り立つ。
単位律:任意の元\(x \in S\)に対して\(e \times x = x = x \times e\)が成り立つ。

結合律に対して、互換図を示すと以下のようになる。
f:id:bitterharvest:20170927062602p:plain
上の図で、\((S \times S) \times S\)と\(S \times (S \times S)\)とが同値である時を強い結合律を満たすと言い、同型である時を弱い結合律を満たすという。従って、少なくとも、弱い結合律を満足するためには
\begin{eqnarray}
\alpha :: (S \times S) \times S \rightarrow S \times (S, S) \\
\alpha ( (x,y), z) = (x, (y,z) )
\end{eqnarray}
を満たさなければならない。

また、単位律に対しては、次のことを満たさなければならない。
\begin{eqnarray}
\lambda :: () \times S \rightarrow S \\
\lambda (\_, x) = x
\end{eqnarray}

\begin{eqnarray}
\rho :: S \times () \rightarrow S \\
\rho (x, \_) = x
\end{eqnarray}

それでは、この定義を実際にHaskellで実装してみよう。上記の定義を満たすようなクラスを\(Cartesian\)と名付け、次のように定義する。

class Cartesian m where
  mu :: (m, m) -> m
  eta :: () -> m

文字列

次に、文字列の集合を上記での\(S\)と考えて、クラス\(Cartesian\)のインスタンスを作ろう。文字列はHaskellでは\([a]\)と表すことができ、また、二項演算子は\(++\)で、単位元は\([]\)であるので、次のようになる。

instance Cartesian [a] where
  mu (x,y) = x ++ y
  eta () = []

実行してみよう。

*Main> mu ("A ", "dog")
"A dog"
*Main> mu (eta () , "a cat")
"a cat"
*Main> mu(" a pig", eta())
" a pig"
*Main> mu ("A ", "dog")
"A dog"
*Main> mu (eta () , "a cat")
"a cat"
*Main> mu("a pig", eta())
"a pig"

乗算

それでは、乗算を利用できる数の集まりを\(Product'\)とし、次のように定義する。

newtype Product' n = Product' n deriving (Eq, Ord, Read, Show)

これに対して\(Cartesian\)のインスタンスを作ろう。二項演算子は乗算\( *\)で、単位元は1である。

instance Num n => Cartesian (Product' n) where
  mu (Product' x, Product' y) = Product' (x * y)
  eta () = Product' 1

実行してみよう。

*Main> mu (Product' 3.5, Product' 4.8)
Product' 16.8
*Main> mu (Product' 4, eta ())
Product' 4
*Main> mu (eta (), Product' 7.5)
Product' 7.5
*Main> mu (Product' 3, Product' 4)
Product' 12

加算

次は、加算を利用できる数の集まりを\(Product'\)とし、次のように定義する。

newtype Sum' n = Sum' n deriving (Eq, Ord, Read, Show)

これに対して\(Cartesian\)のインスタンスを作ろう。二項演算子は加算\( +\)で、単位元は0である。

instance Num n => Cartesian (Sum' n) where
  mu (Sum' x, Sum' y) = Sum' (x + y)
  eta () = Sum' 0

実行してみよう。

*Main> mu (Product' 3, Product' 4)
Product' 12
*Main> mu (Sum' 7.9, Sum' 4.3)
Sum' 12.2
*Main> mu (Sum' 6, eta ())
Sum' 6
*Main> mu (eta(), Sum' 5.6)
Sum' 5.6

余積

最後に、余積に対してもインスタンスを作ってみよう。余積も二項演算子には変わりはないが、インスタンスを作るには少し工夫がいる。余積はHaskellでは\(Either\)である。

instance (Cartesian a, Cartesian b) => Cartesian (Either a b) where
  mu (Right x, Right y) =  Right $ mu (x, y)
  mu (Left x, Left y) =  Left $ mu (x, y)
  mu (x@(Left _), _) = x
  mu (_, x@(Left _)) = x
  eta () = Right $ eta ()

実行してみよう。なお、実行に当たっては、出力のデータ型を指定しないと結果が得られないものがある。最初と最後の方の実行例にみられるが、これは\(Right\)あるいは\(Left\)のデータ型が確定しない場合に起こる。

*Main> mu (Right (Product' 3), Right (Product' 7)) :: Either String (Product' Int)
Right (Product' 21)
*Main> mu (Right (Product' 3.5), Right (Product' 7)) :: Either String (Product' Float)
Right (Product' 24.5)
*Main> mu (Left "Error1", Right (Product' 7))
Left "Error1"
*Main> mu (Right (Product' 3.5), Left "Error2")
Left "Error2"
*Main> mu (Left "Error1", Left "Error2") :: Either String (Product' Int)
Left "Error1Error2"
*Main> mu (Right (Product' 11), eta ()) :: Either String (Product' Int)
Right (Product' 11)
*Main> mu (eta (), Right (Product' 13)) :: Either String (Product' Int)
Right (Product' 13)

4) Haskellでの定義

前回の記事で、Haskellではモノイドは次のように定義した(但し、\(mconcat\)は省いても構わないので省略した)。

class Monoid m where
  mappend :: m -> m -> m
  mempty :: m

デカルト積を用いての定義は次のようになっていた。

class Cartesian m where
  mu :: (m, m) -> m
  eta :: () -> m

\(mu\)の型シグネチャ\((m, m) \rightarrow m\)は、カリー化を行えば、\(m \rightarrow m \rightarrow m\)となる。従って、\(mappend\)と\(mu\)は同じことを表していることが分かる。
さらに、 \eta単位元を導き出す式であるので、\(mempty\)と同じである。これを用いると、前回の記事で示したHaskellでの定義は次のように置き換えることができる。

class Monoid m where
  mu :: m -> m ->  m
  eta :: () -> m

但し、結合律と単位律は満足しなければならない。

書き換えたモノイドのインスタンスを示してみよう。

instance Monoid [a] where
  mu x y = x ++ y
  eta () = []

newtype Product n = Product n deriving (Eq, Ord, Read, Show)
instance Num n => Monoid (Product n) where
  mu (Product x) (Product y) = Product (x * y)
  eta () = Product 1

newtype Sum n = Sum n deriving (Eq, Ord, Read, Show)
instance Num n => Monoid (Sum n) where
  mu (Sum x) (Sum y) = Sum (x + y)
  eta () = Sum 0

instance Monoid a => Monoid (Maybe a) where
  mu Nothing x = x
  mu x Nothing = x
  mu (Just x) (Just y) = Just $ mu x y
  eta () = Nothing

instance Monoid b => Monoid (Either a b) where
  mu (Right x) (Right y) =  Right $ mu x y
  mu x@(Left _) _ = x
  mu _ x@(Left _) = x
  eta () = Right $ ita ()

上のプログラムで、()は、二項演算子が積である時は終対象であり、余積である時は始対象であることが分かる。これはたまたまそうなったのではなく、積と余積が双対関係にあることから、一般的にこのようになる。

モノイドを代数学のレベルから圏論でのレベルまで持ち上げてきたので、次回はさらなる抽象化を試みる。

三河国分寺・尼寺と豊川稲荷を訪ねる

秋分の日(23日)は、三河国分寺・尼寺を訪ねた。741年に聖武天皇が全国の国々に国分寺国分尼寺を建立するようにとの詔を発した。三河の国は、この当時の中心的な地域であったのだろう、豊川の地に二つの寺が建立された。

三河国分寺・尼寺は、豊川市国府にある。国府は、地元の人でないと分からないのだが、「こう」と発音する。
f:id:bitterharvest:20170924135104p:plain

名鉄線の国府で降り、徒歩で20分程度のところに三河国分寺・尼寺がある。この日は幸い秋晴れで、散策しながら、訪れるのに最適であった。

名鉄豊川線豊川稲荷駅から国府駅行の2両電車で向かった。
f:id:bitterharvest:20170924135645j:plain

最初に訪れたのは三河国分寺である。ここは、野草が生い茂る広場だ。お彼岸のこの日、曼殊沙華がきれいに咲いていた。
f:id:bitterharvest:20170924135842j:plain

このお寺には、銅鐘以外に残されているものはない。
f:id:bitterharvest:20170924140317j:plain

しばらく、国分寺跡の周りを散策した後で、国分尼寺へ向かう。ここは、南大門が復元されている。
f:id:bitterharvest:20170924140827j:plain
f:id:bitterharvest:20170924140857j:plain

金堂や講堂の跡も復元されている。
f:id:bitterharvest:20170924141211j:plain
f:id:bitterharvest:20170924141251j:plain

国分尼寺を発掘する前には、これらの遺跡の上にお寺が立っていたそうだ。このお寺を敷地の横に立て直して、発掘作業をし、復元したと自称ボランティアのおじさんが説明してくれた。下の写真は立て直しされたお寺である。しかし、現在では、ご住職もなくなり、その奥さんもなくなってしまって、お坊さんのいないお寺になっているとのことであった。
f:id:bitterharvest:20170924141844j:plain

近くに資料館があったが、ボランティアのおじさんが、「見てもつまんない」と言うので、国府の駅に向かい、豊川稲荷駅に戻った。

豊川稲荷駅前には、お稲荷さんの狐の像がある。
f:id:bitterharvest:20170924143629j:plain
参道に沿っては、狐さんの好物の稲荷寿司のお店が多い。
f:id:bitterharvest:20170924143844j:plain

豊川稲荷は、神社かと思っていた。しかし、境内に入るとお経が聞こえる。「あれ」と思って、調べると曹洞宗のお寺だ。
曹洞宗法王派の東海義易によって1441年に創建され、室町時代の末期、今川義元によって伽藍が整備されたそうだ。

お寺にもかかわらず鳥居がある。ただし、見慣れた朱色ではない。
f:id:bitterharvest:20170924144640j:plain

本殿は立派だ。
f:id:bitterharvest:20170924144742j:plain

奥の院に向かう参道にはのぼりが立ち並んでいる。
f:id:bitterharvest:20170924144852j:plain

奥の院の先には霊狐塚がある。狐さんが沢山いる。
f:id:bitterharvest:20170924145012j:plain
f:id:bitterharvest:20170924145035j:plain

本殿の近くには、小さな庭園もあった。
f:id:bitterharvest:20170924145226j:plain

産まれたばかりの赤ちゃんの健康をお祈りして、病院へと向かった。

縄文時代後期、最も多数の人骨が発見された吉胡貝塚を訪ねる

先週、息子のところに孫が生まれたので、赤ちゃんを見がてら愛知県の三河地方を訪れた。以前から訪問したいと思っていた吉胡(よしご)貝塚には、9月22日に足を運んだ。

この貝塚は、大正11,12年に京都大学の清野謙次教授により、300体を超える人骨が発見されたところとして知られている(その後の発見も加えると340体)。
f:id:bitterharvest:20170924095136j:plain

日本で最も多くの人骨が発見された遺跡だ。吉胡貝塚渥美半島の中ほどにある。
f:id:bitterharvest:20170924093446p:plain

豊橋からは、豊橋鉄道渥美線を利用する。出発駅は新豊橋だ、電車は2両連結。かつて、東急電鉄で使われた懐かしい電車だ。それぞれの電車には、花の名前がつけられていて、我々の乗った電車は「椿」であった。
f:id:bitterharvest:20170924094639j:plain

終点の三河田原駅で降りる。運が悪いことに、この駅に近付いたころから小雨になった。
f:id:bitterharvest:20170924095044j:plain

街の景色を楽しみながら、田原城にも寄って、目的地に向かおうと思っていたが、雨に濡れるのが嫌なので、タクシーで直接、吉胡貝塚に向かった。タクシーが止まった先には、こじんまりとしているが、立派な資料館がある。
f:id:bitterharvest:20170924095951j:plain

資料館の中には、貝塚を発掘している様子も示されている。吉胡貝塚は、渥美半島の内部にあるように見えるが、近くまで田原湾が入り込んでおり、そばにはこの湾に流れこむ汐川がある。この貝塚縄文時代後期から晩期にかけての遺跡だ。この時期は暖かかった中期が終わり、寒冷期となる。多くの地域で人口が激減したが、この地域は住みやすかったのだろう。近くには、191体の人骨が発見された伊川津(いかわづ)貝塚や90体の稲荷山(いなにやま)貝塚がある。これらの貝塚も縄文後期から晩期の遺跡である。
f:id:bitterharvest:20170924100213j:plain

貝塚から採取された貝なども展示されていた。
f:id:bitterharvest:20170924104817j:plain

この時代には犬も飼われていたようで、人間の人骨と一緒に犬の骨も見つかっている。
f:id:bitterharvest:20170924105032j:plain

この地域の貝塚の特徴は、歯を抜いたり(抜歯)、削ったり(叉状研歯)する習慣があったことだ。ふじのくに地球環境史ミュージアムの日下宗一郎さんが、論文「縄文時代人の食性と集団間移動−安定同位体分析による試論」で、食性によって抜歯の仕方が異なっていたのではないかと報告している。また、刺青をする習慣もあった。
f:id:bitterharvest:20170924110932j:plain

このころは装飾も進み、貝殻を利用した指輪も発見されている。
f:id:bitterharvest:20170924112654j:plain

資料館の外は史跡公園になっている。
f:id:bitterharvest:20170924112834j:plain

昭和26年に発掘調査した現場も復元されている。5体の縄文人と2対の縄文犬だ(もちろん、骨は模型)。
f:id:bitterharvest:20170924113021j:plain

また、貝塚の平面もある。
f:id:bitterharvest:20170924113225j:plain

昭和26年の発掘で、右腕に4個、左腕に7個の指輪をした50歳前後の女性が発掘された。その場所も記されていた。
f:id:bitterharvest:20170924113454j:plain
なお、資料館にはこの女性の骨の模型がある。
f:id:bitterharvest:20170924120325j:plain
骨は入りいろな姿で埋葬されたようで、資料館には、盤上集骨墓も展示されていた。
f:id:bitterharvest:20170924121242j:plain

公園の風景をいくつか載せよう。
f:id:bitterharvest:20170924113559j:plain
f:id:bitterharvest:20170924113632j:plain
f:id:bitterharvest:20170924113735j:plain

公園の見学を終えたころ、雨が強くなってきたので、タクシーを呼んで、帰ることとした。

雨のため、予定より短い旅になってしまったが、渥美半島の訪問は初めてであったし、また、息子が勤務する会社の近くまで行け、それなりに楽しい旅行であった。

モノイドーHaskellでの表現

13.モノイド

モノイド圏は、集合の要素を射に、二項演算子を射の合成に、そして、単位元を恒等射にし、結合律、単位律が成り立っているものをいう。

例えば、整数の乗算の場合には、
1) 対象:シングルトン(通常星印で表される)
2) 射:整数
3) ドメイン、コドメイン:シングルトン
4) 恒等射:1
5) 合成: \(\times\)
① 結合律:満足
② 単位律:満足

しかし、上記の例でみたように射は集合の要素となるので、圏としては、余りにも細かいものが見えて気持ちよくない。そこで、構成要素を隠すように抽象化したい。しかし、いきなり、抽象化の議論を進めるのは気が引けるので、モノイドとは何かをHaskellを利用して慣れておこう。

13.1 Haskellでのモノイド

HaskellではモノイドはData.Monoidでクラスとして次のように定義されている。

class Monoid m where
  mempty :: m
  mappend :: m -> m -> m
  mconcat :: [m] -> m
  -- defining mconcat is optional, since it has the following default:
  mconcat = foldr mappend mempty

これに従えば、モノイドを使うときは\(mempty\)と\(mappend\)を定義する必要がある。なお、\(mappend\)は、中置関数\(<>\)でしばしば置き換えられる。

x <> y = mappend x y

また、結合律と単位律を満たさなけらばならないので、次の式を満たさなければならない。

-- Identity laws
x <> mempty = x
mempty <> x = x
-- Associativity
(x <> y) <> z = x <> (y <> z)

それでは、文字列の結合をモノイドとして定義しよう。次のようになる。

instance Monoid [a] where
  mempty = []
  mappend x y = x ++ y
  mconcat = concat

積は次のようになる。積は数(\(Num\))に対する二項演算子であるが、モノイドとして定義するときは、\(Product\)と呼ばれる新しいデータ型(コンテナ)を用意する。

newtype Product n = Product n
 
instance Num n => Monoid (Product n) where
  mempty = Product 1
  mappend (Product x) (Product y) = Product (x * y)

和(余積)は次のようになる。ここでも、\(Sum\)と呼ばれる新しいデータ型(コンテナ)を用意する。

newtype Sum n = Sum n
 
instance Num n => Monoid (Sum n) where
  mempty = Sum 0
  mappend (Sum x) (Sum y) = Sum (x + y)

それでは利用してみよう。なお、Data.Monoidでは\(getProduct,getSum\)により、演算結果を数(\(Num\))のデータ型で表す関数を用意している。

Prelude> import Data.Monoid
Prelude Data.Monoid> [1,2,3] <> [5,6]
[1,2,3,5,6]
Prelude Data.Monoid> [1,2,3] <> []
[1,2,3]
Prelude Data.Monoid> [] <> [2,3,4]
[2,3,4]
Prelude Data.Monoid> Product 3 <> Product 5
Product {getProduct = 15}
Prelude Data.Monoid> Product 3 <> Product 1
Product {getProduct = 3}
Prelude Data.Monoid> Product 1 <> Product 2.34
Product {getProduct = 2.34}
Prelude Data.Monoid> getProduct $ Product 32.5 <> Product 2.34
76.05
Prelude Data.Monoid> getProduct $ Product (3 / 4) <> Product ( 6 / 7)
0.6428571428571428
Prelude Data.Monoid> getSum $ Sum 4 <> Sum 5
9
Prelude Data.Monoid> getSum $ Sum 4 <> Sum 0
4
Prelude Data.Monoid> getSum $ Sum 0 <> Sum 5.5
5.5
Prelude Data.Monoid> getSum $ Sum ( 2.3 * 5) <> Sum (5.5 + 3.2)
20.2

横浜:吉田新田を訪ねる

今回(19日)は、江戸時代の初めに開発された吉田新田の跡を訪ねた。この場所は、明治になると伊勢佐木町を中心に日本でも有数の商業地として栄えることとなる。しかし、戦国時代が終わり、江戸幕府が開かれたころは、大きな入り海だった。

横浜には、関内と関外と呼ばれる二つの地域がある。吉田新田は関外の大部分を占める。現在のこの地域は、かつてほどの勢いはないが、前述したように、伊勢佐木町よこはまばしなどの商店街を有する繁華街だ。また、関内は山下公園や横浜球場や中華街を有するデート・スポットだ。地図で示そう。
f:id:bitterharvest:20170920102134p:plain
地図で、左下隅から上中央に向かって水色の線がある。これは大岡川である。また、同じ左下隅から右中央に向かって薄茶色の線がある。これは高速道路だ。高速道路と大岡川に挟まれた区域が関内と関外である。高速道路は途中の石川町で分かれて大岡川の方に向かう線がある。これに沿って、関内と関外とに分けられ、右上の海側の方が関内で、左下の陸側の方が関外である。高速道路の下は中村川が流れている。この川はまっすぐに海に流れるわけではなく、高速道路が別れるところで直角に折れて、大岡川の方に向かって流れる。この部分は派大岡川と呼ばれ、関内と関外を分ける。

江戸時代初めの関外は海よりの半分程度のところまでしか小舟が入れないような浅瀬の入り海だった。また、関内は、高速道路の側から砂州が伸びていて、入り海を閉じ込める役割をしていた。この砂州とその近隣は、浜が横に伸びている形をしていたのでそのように呼ばれたものと思うが、室町時代から横浜村と呼ばれるようになった。江戸時代の終わりごろまでは現在とは全く異なり寒村であった。

関内・関外と呼ばれるようになったのは、江戸時代の終わりである。黒船が来航し、その結果、1859年に日米通商条約によって横浜は開港され、山下公園や中華街を含む地域が外国人居留地となる。このとき、横浜村の砂州の根元に堀が構築され(高速道路の分岐点から海に向かっている箇所)、堀川と呼ばれた。外国人居留地大岡川、派大岡川、堀川で囲まれ、出入りするためには関所(吉田橋)を通らなければならなかった。そのため、この三つの川で囲まれた地域を「関の内」ということで、関内と呼ばれるようになる。なお、関内は、海に向かって右半分が外国人が住む町で、左半分が日本人の居住地となった。地図を見ると、道と道の間隔が異なるので、その差は歴然としている。

関外は関内と対比的に「関の外」ということで関外と呼ばれるようになった。吉田新田は大阪生まれの江戸の材木商である吉田勘兵衛(1611-1686)により、1656年に開発が始められる。翌年、大岡川の決壊で堤防が壊れ、1659年に改めて工事をやり直し、1667年に完成する。最初の工事を始めてから11年の歳月を要した。開発前の入り海とその時の計画図と思われるもの示したのが下図である。
f:id:bitterharvest:20170920111151p:plain

上の図は、最初に示した横浜市の図を右回りにおよそ90度以上回転してある。入り海は釣鐘のような形をしている。また、開港前の関内・関外は次のようになっていた。
f:id:bitterharvest:20170920112448p:plain

吉田新田の大きさは115万平米、丁度、東京ディズニーランドとディズニーシーを合わせたぐらいの大きさだ。石高は1000石だ。1石はおよそ150Kgなので(1石は大人が1年間に食べる量)、約150トンとれたことになる。20トン積の大型トラックで7~8台となる。

鬼頭宏さんによれば、江戸時代が始まった1600年の日本の人口は1227万人、1700年には2829万人、1721年には3128万人、1873年(明治6年)には3330万人である。江戸幕府が開かれて最初の120年間で人口は2.5倍に膨れ上がり、その後の150年は横ばいとなる。このため、江戸時代前半には、人口急増に対応するため、各地で新田開発が行われた。吉田新田もその一例である。

吉田新田の開発は、堤を築いて川を両脇に押しのけ、内部を干上がらせるという工法で行われた。内部の水を抜くために、潮の干満に応じて堰の上げ下げもなされた。また、付近の山からの土砂で埋めることも同時に行われた。この当時の土木技術は戦国時代に築城が盛んにおこなわれたこともあり、高度に発達していたようだ。

前置きが長くなったが、吉田新田巡りは桜木町の駅から大岡川を分離する地点まで、地下鉄5駅(桜木町、関内、伊勢佐木長者町、坂東橋、吉野町)の周囲をあちこち巡りながら3時間歩いた。最初にめざした地点は、野毛山公園である。一段と高くなっているところで、展望台からは、吉田新田の跡を一望に見渡すことができる。

公園までの道のりにいくつかの名所があるので、それも併せて見学した。最初の訪問場所は、一昨年改修工事が完了し、新装なった成田山横浜別院である。ここは、易断で知られる高島嘉右衛門の協力により明治3年(1870)に建立された。
f:id:bitterharvest:20170920200401j:plain

さらに、伊勢山皇大神宮を訪れる。この神宮も明治3年に創建された。
f:id:bitterharvest:20170920200451j:plain

野毛山公園に入ると、横浜市の水道事業に貢献した英国人技師ヘンリー・スペンサー・パーマーの胸像がある。彼は、明治18年(1985)に相模川の支流の道志川を水源にして、野毛山配水池までの48Kmにわたる水道建設を開始し、同20年に日本で最初となる近代水道を完成させた。
f:id:bitterharvest:20170920201811j:plain

昭和38年(1963)には東京オリンピックが開催されたが、蹴球・バレーボール・バスケットボールの予選が横浜で行われた。それを記念する碑が公園にある。
f:id:bitterharvest:20170920202821j:plain

公園にある展望台に上って、吉田新田のあった地域を一望する。ビルが隙間なく立ち並んでいる。
f:id:bitterharvest:20170920202916j:plain
f:id:bitterharvest:20170920202938j:plain

公園を離れて、大岡川にかかる長者橋へと歩みを進める。この辺りは、吉田勘兵衛の屋敷跡である。今でも、子孫が経営する吉田興産や吉田パーキングの建物がある。
f:id:bitterharvest:20170920203539j:plain
f:id:bitterharvest:20170920203559j:plain

また、吉田家の庭先にあった大井戸を見る。この井戸は、200年にわたって付近の住民の飲料水になったとのことである。
f:id:bitterharvest:20170920204005j:plain

吉田新田は今は商業地となっているが、その中でも一番賑やかである伊勢佐木町を歩く。ここには、明治時代に創業したお店が何軒かある。
f:id:bitterharvest:20170920204209j:plain
f:id:bitterharvest:20170920204238j:plain
f:id:bitterharvest:20170920204321j:plain
f:id:bitterharvest:20170920204358j:plain

また、青江三奈伊勢佐木町ブルースの碑もある。
f:id:bitterharvest:20170920204513j:plain

吉田新田の真ん中あたりには、よこはまばし商店街がある(写真は大通公園から商店街を撮った)。
f:id:bitterharvest:20170920204645j:plain

よこはまばし商店街は平日にも関わらす、多くの人でにぎわっていた。
f:id:bitterharvest:20170920205320j:plain

黄金町まで進むと珍しい旗屋さんがある。
f:id:bitterharvest:20170920205615j:plain

吉田新田開発後に最初にかけられた橋が道慶橋だ。写真は道慶橋の上から大岡川を撮ったものだ。
f:id:bitterharvest:20170920211016j:plain

大岡川の分離地点の近くには、吉田新田の守護神として1673年に創建された「お三の宮日枝神社」がある。数日前にお三の宮の祭が行われたため、まだ、飾りが残っていた。
f:id:bitterharvest:20170920211336j:plain
f:id:bitterharvest:20170920211401j:plain

また、境内には創建当時の手水鉢がある。
f:id:bitterharvest:20170920211605j:plain

さらに、近くには用水堰の守り神社としての堰神社がある。
f:id:bitterharvest:20170921083454j:plain

さて、最後の目的地、大岡川中村川大岡川に分かれる地点に到着した。真ん中の奥が分流前の大岡川。左側が中村川、右側が分流後の大岡川である。

台風一過が続く暑い中、3時間余りの行程は無事終了した。
f:id:bitterharvest:20170920211801j:plain

キャスト・アウェイ (Cast Away) - 4年間の無人島での漂流生活の後に彼を待ち受けていた不条理な運命!

今回紹介する映画は2000年制作のトム・ハンクス演ずるキャスト・アウェイだ。

俳優の役作りはすごいなあと感じさせられる時がある。この映画もその一つだ。映画が始まるとすぐに、宅急便のトラックからトム・ハンクス扮するチャックが下りてくるが、こんなに大きな図体だったかと疑問を抱かせ、思わず尋ねたくなる場面がある(写真は少し後の場面でロシアで仕事に従事しているときのもの)。
f:id:bitterharvest:20170915055441j:plain
後で調べると、中年太りの男性を演ずるために50ポンド(23Kg)も体重を増やしたそうだ。

そして、ビジネスマン役での場面どりを終了した後、1年間ほど撮影を中断し、その間に髪や髭をぼうぼうにはやし、無人島での役に備えたとのことだ。
f:id:bitterharvest:20170915055501j:plain

タイトルのキャスト・アウェイは、「世の中から見捨てられた人」、あるいは、「船が難破したため漂流させられた人」を意味する。飛行機が海上に不時着し、救命ボートで無人島に到着し、そこで、4年間の孤独な生活を送ることになるので、「漂流者」と訳すのがよいと思う。しかし、無人島での生活の後に待ち受けているのは不条理な現実だ。観客が最も心を打たれる場面はここなので、この部分を強調すると、「見捨てられた人」と言いたかったのではと感じさせられる。

映画のあらすじは次のようになっている。

クリスマス・パーティーをしている最中に、緊急の仕事が入ったチャックは、恋人のケリー(ヘレン・ハントが演ずる)に大みそかには帰ってくると言って、貨物便に乗り込む。その時、ケリーの祖父からの形見である懐中時計がクリスマス・プレゼントとして渡される。そして、時計のふたの裏側にはケリーの写真が貼ってある。

運の悪いことに、飛行機は太平洋上で墜落し、チャックは救命ボートで無人島に漂着する。待っていたのは、生きていくための過酷な戦いと、襲ってくる孤独との葛藤である。バレーボールについた手形の血判に目や口を描き、ウィルソンと名付けて仲間として擬人化し、ケリーの写真に望みを託して、4年間生き抜く。
f:id:bitterharvest:20170915091554j:plain

映画のほとんどは4年間の無人生活が占めており、トム・ハンクスが素晴らしい演技をする。

やっとの思いで故国に戻るが、4年間という歳月は残酷である。思い焦がれていたケリーは、すでに結婚していて子供もいる。

帰国した後、チャックは思い切ってケリーに会いに行く。彼女の自宅での会話がこの映画の中で最も感動する場面だが、ここは読者に残しておこう。ただし、最後の場面は次のようになっている。彼が去ろうとして車を走らせ始めたとき、激しい雨の中をケリーが走って追ってくる。二人は抱き合い、そして、ケリーは車に乗り込む。この時のケリーの演技が圧巻で、激しい心臓の鼓動に伴って、上半身が強く脈動する。ケリーのきっぱりとした決断が伝わってくる。
f:id:bitterharvest:20170915112358j:plain
二人はこのまま走り出すのかと思った瞬間、チャックが言う。

"You have to go home."
「家に戻りなさい。」

場面は変わって、チャックが友人にこの時の決着について説明する。

"We both had done the math, and Kelly added it all up."
この文章は意訳しないと分かりにくい。直訳すると、「二人とも計算したんだ。そして、ケリーは合計を得るまであれもこれも加えたのだ。」となるのだが、分かったようで、分からない気分にさせられる。使われている単語は易しいのだが、すんなりと頭に入ってくる表現ではない。

このため、頭をひねって考える必要がある(この「ひねる」という日本語の表現は同じように外国人には通じにくい)。計算するということは、頭脳をフル回転させるという意味に転じる。合計を得るまであれもこれも加えたということは、様々なことを考慮に入れて納得のいく結論を出すという意味に転じる。従って、
「二人とも熱心に考えたのだ。そしてケリーはケリーなりに納得のいく結論を導き出した。」

"She knew she had to let me go."
「ケリーは俺を去らさせなければいけないと分かっていた。」
"I added it up, knew that I'd lost her."
「俺も納得のいく答えを出した。ケリーを失うということを分かっていた。」
"'Cause I was never gonna get off that island."
「だって、島からは決して脱出できないのだから。」

そして、チャックは無人島で考えていたことを話し始める。
"I was gonna die there, totally alone."
「たった一人で、島で死んでいくだろう。」
"I mean, I was gonna get sick or I was gonna get injured or something."
「そう、病気になるか、怪我をするか、あるいは、他のことで。」
"The only choice I had, the only thing I could control was when and how and where that was gonna happen."
「俺が持っている唯一の選択は、俺が意図的にできる唯一のことは、いつ、いかにして、どこで、それを行うかということだけだ。」
"So I made a rope."
「そこで、ロープを作った。」
"And I went up to the summit to hang myself."
「そして、首つり自殺するすためにいただきに行った。」
"But I had to test it, you know ?"
「でも、まず試してみる必要があった。」
"Of course."
「もちろん。」
"You know me."
「俺の性分を知ってるだろう。」
"And the weight of the log snapped the limb of the tree."
「(身代わりに使った)丸太の重さが木の枝を折ってしまった。」
"So I couldn't even kill myself the way I wanted to."
「なので、俺が望んだ方法で自殺することさえできなかった。」
"I had power over nothing."
この言い回しも、やさしい単語の組合せなのだが、意味が分かりにくい。"over nothing"は「つまらないことに」を表す。例えば、次のような使い方をする。
"She got exited over nothing."
「彼女はつまらないことに興奮した。」
従って、ここでの"I had power over nothing."の意味は、
「何もできなかった。」
独白はまだ続くが、このあとは映画を観て欲しい。

最後の場面では、中年太りの男性ではなく、見慣れたトム・ハンクスに戻っている。
f:id:bitterharvest:20170915112321j:plain

今回の会話の部分には、なじみの少ない慣用句が二つあった。Googleで検索すると、英語を母国語としている人も質問しているので、知らない人も多いようだ。このような慣用句に出くわすと、何を言っているのかなあと考えだすために、次の言葉が入ってこなくなる。ついていけない状態に陥るのだが、聞き流して、前後関係から理解することが肝要だ。

モナドと自然変換

12.圏論でのモナド

Haskellでのモナドについて論じてきたが、モナド圏論の中の一つの圏でもある。そこで、ここではモナドが圏となるための条件を求めて見よう。

圏論においては自然変換は重要な役割をなすが、モナドは自然変換が主要な枠組みとなっている数学概念でもある。

まず、Haskellではモナドは\(join\)と\(return\)を用いて次のように定義した。

class Functor m => Monad m where
  join :: m (m a) -> m a
  return :: a -> m a

また、Haskellでの記述を圏論での記述に直すことを考えよう。モナドは自身の圏に写像する関手である。そこで、モナドの圏\(\mathcal {C}\)は、対象が関手で、射が関手間の写像(自然変換)として構成することにしよう。そして、Haskellモナド\(m\)は圏論での関手\(T\)として、\(join,return\)は圏論での自然変換\(\mu\), \eta として表すことにしよう。

下図の互換図に示すように、\(return\)では、\(a\)は恒等関手\(Id\)となり、\(m \ a \)は関手\(T\)となる。
f:id:bitterharvest:20170905115110p:plain
これより、\eta :: Id \rightarrow Tとなる。 \etaは、\(\mathcal {C}\)の内部構造を維持しての関手から関手への写像となっているので、自然変換である。

また、\(T \circ T\)を\(T^2\)と書くと、下図の互換図より\(\mu:: T^2 \rightarrow T \)を得る。これも内部構造を保っての関手から関手への写像なので、自然変換である。
f:id:bitterharvest:20170905115136p:plain
ところで、モナドが圏となるためには、\(T\)に対して結合則が成り立つ必要がある。即ち、\(T \circ T^2= T^2 \circ T\)でなければならない。それでは、左式を\(\mu\)を用いて表してみよう。

\(T \circ T^2\)を互換図で表すと次のようになる。なお、下図で\(T\)から\(T\)への恒等な自然変換を\(I_T\)で表した。
f:id:bitterharvest:20170905115156p:plain
この互換図より、\(\mu \circ I_T=\mu \)を得る。

\(T^2 \circ T\)を互換図で表すと次のようになる。
f:id:bitterharvest:20170905115213p:plain

この互換図より、\( I_T \circ \mu =\mu \)を得る。
これより\(\mu \circ I_T=\mu = I_T \circ \mu \)が満たさなければならないことが分かる。

これを互換図で表現すると次のようになる。
f:id:bitterharvest:20170905115233p:plain

モナドが圏であるためには、関手\(T\)は単位律をも満たす必要がある。単位律は\(T \circ Id = T = Id \circ T\)である。

\(T \circ Id \)より下図の互換図を得る。
f:id:bitterharvest:20170905115248p:plain
これより I_T \circ \eta = \etaを得る。

\(Id \circ T \)より下図の互換図を得る。
f:id:bitterharvest:20170905115312p:plain
これより \eta \circ I_T = \etaを得る。

従って、 I_T \circ \eta =\eta = \eta \circ I_T が満たさなければならないことが分かる。

これを互換図で表現すると次のようになる。
f:id:bitterharvest:20170905115331p:plain

\(I_T\)は\(T\)と見なしてもよいので、Mac LaneやAwodeyの教科書には次の互換図が掲載されている。
f:id:bitterharvest:20170905115350p:plain


最後に圏論としてのモナドをまとめよう。

モナドの圏としての構成:
1) 対象:関手\(T\)、恒等関手\(Id\)
2)射:\(\mu\), \eta
3)ソース、ターゲット:\(\mu: T^2 \rightarrow T\), \eta:: Id \rightarrow T
4)恒等射:\(I_T: T \rightarrow T\)
5)結合:\(\mu\)と \etaを結合したものは、下図に示すように、組合せによらず\(\mu\)となる。
f:id:bitterharvest:20170905115410p:plain

さらに、次の二つを満たす必要がある。
\( \mu \circ T = T \circ \mu \)
 T \circ \eta =\eta = \eta \circ T

以上で、圏論におけるモナドの構造を示すことができた。

横浜関内の歴史的建築を訪ねる

9月1日は東京や横浜に住んでいる人々にとっては忘れてはならない日だ。94年前(大正12年)のこの日、関東大震災が発生した。地震の規模はマグニチュード7.9、東京・横浜の震度は6だ。発生した時間は11時58分、丁度お昼時だ。

震源地は相模湾で、震源に近かった横浜は東京よりも大きな被害を被った。当時の横浜市(市域は中心部のみ)の人口は約42万人で、全壊した住家は16,000棟、死者は23,000人であった。地震によって倒壊した家が多く、また、その後に生じた火災により死亡した人も多い。

防災の日に、神奈川県立歴史博物館が「横浜正金銀行と横浜関内の関東大震災復興建設をめぐる」という見学会を開催したので、それに参加した。現在の神奈川県立歴史博物館から山下公園までの震災後の復興に関連する建物を見学した。

神奈川県立歴史博物館となっている建物は、大震災の頃は横浜正金銀行本店の本館であった。
f:id:bitterharvest:20170902090249j:plain

この本館は、関東大地震では倒壊しなかった。付近では火災が発生し、それを避けるために、正門から100人、通用門から100人が逃げ込んだそうだ。13時には延焼から逃れるために鉄の頑丈な扉は閉じられる。建物の中には、行員140人と逃げ込んできた200人、合わせて340人が避難していた。

火勢は強く、本館の上階に火が入り、内部が燃え始めた。避難している人たちは上の階から下の階へ、そして、地下室へと逃げ込んだ。火事の熱で地下室はとても熱く、炊事場の桶に貯めてあった水を唇に浸すなどして耐えたそうだ。15時半ごろには1階まで火は広がったが、幸いに、地下室には延焼せずに16時半ごろには内部の火災は治まった。周辺も鎮火しており、外へ出たとのことだ。また、門扉が閉まった後に、本館に駆けつけてきた人々もたくさんいたようで、本館の周りにはいくつもの死体があったそうだ。

横浜正金銀行の本館は1904年(明治37年)の竣工で、設計者は妻木頼黄(つまき よりなか)である。彼は明治時代の3巨頭の一人と言われる建築家で、大蔵省をはじめとする数多くの官庁建築を手がけた。赤レンガ倉庫も彼の設計である。国会議事堂を設計することを望んでいたが、その夢は果たされなかった。

本館は古典主義様式である(古典主義は、ルネサンス建築、バロック建築新古典主義建築などの総称で、古代ローマ時代に建てられたオリジナルの建築の知識を発展、再構成した建築を言う)。コリント式の柱を巡らせ、大きなドームを持つネオ・バロック式の建築である。建物の高さは17mであるのに対し、ドームは19mもある。

隣にあるのが、旧川崎銀行横浜支店の建物だ。
f:id:bitterharvest:20170902102105j:plain
この建物は1922年(大正11年)に竣工している。関東大震災では被害を受けなかった。妻木の弟子である矢部又吉が設計した。ファサード2面を残して建て替えられている。元の建物は古典主義様式である。

次に見学したのは旧横浜銀行集会所である。現在は横浜銀行協会が利用している。
f:id:bitterharvest:20170902105305j:plain
妻木の弟子で国会議事堂を設計した大熊義邦と彼の娘婿の林豪蔵が設計し、1936年(昭和11年)に竣工している。銀行の建物は古典主義様式であった時代に、幾何学模様をモチーフにしたアール・デコ調のデザインを取り入れている。

横浜郵船ビルも1936年の竣工である。この界隈では、最後の古典主義様式の建物である。f:id:bitterharvest:20170902110901j:plain
コリント式のがっしりとした柱が特徴である。

さらに進んで、神奈川県庁に行く。
f:id:bitterharvest:20170902111346j:plain
何度か立て直しされているが、これは4代目の県庁である。1928年(昭和3年)の竣工で、コンペを行い一等当選案に基づいて設計された。古典主義を用いているが、細部では、スクラッチタイル張りの外壁や屋根の銅板による幾何学的な様式などアール・デコを取り入れ、新しい表現法に挑んでいることが感じられる。また、上部には和式の塔を戴いているのも特徴である。

県庁の内部にも面白い装飾がある。正面の階段の両翼に装飾灯がある。
f:id:bitterharvest:20170902112540j:plain
柱にも和風の装飾がある。
f:id:bitterharvest:20170902112705j:plain
4階の階段を上がりきったところにも装飾がある。
f:id:bitterharvest:20170902112758j:plain
戦前は、正庁だったそうだ。この装飾の反対側には天皇の御影が掲げられていたそうだ。

屋上に上ると、港や付近の建物を展望できる。
横浜三塔を見学する。キングの塔は、神奈川県庁の上にある塔である。
f:id:bitterharvest:20170902113817j:plain
クイーンの塔は横浜税関本関庁舎の塔である。建物はアール・デコである。
f:id:bitterharvest:20170902114035j:plain
ジャックの塔は、開港記念横浜会館の塔である。
f:id:bitterharvest:20170902114211j:plain
塔の下の建物は辰野式と呼ばれるフリークラシック・スタイルである。
f:id:bitterharvest:20170902114324j:plain

県庁の屋上からは象の鼻も見ることができる。
f:id:bitterharvest:20170902121250j:plain
幕末末期の開港に伴って、イギリス波止場が作られたが、その形が象の鼻に似ていたことから名づけられた。改造されてこのような形でない時もあったが、2009年に復元された。

最後の見学場所はニューグランドホテルである。
f:id:bitterharvest:20170902121906j:plain

震災の後に、外国人求まれるようなホテルということで、地元の有志が資金を出し合って開設したとのことであった。古典主義様式をとりながらも、アール・デコ調でまとめられたホテルである。丸みを帯びたコーナーには竣工年を刻んだ浮彫がある。

若いころからよく訪れたルートであったが、建築物にこれほど注目して見学したことはない。この時代の主要な建築様式を学ぶことができ、有意義な一日であった。

ビフォア・サンセット(Before Sunset)-9年後の再開

ビフォア・サンセットは、恋人までの距離(Before Sunrise)の続編で、9年後に作られた。
f:id:bitterharvest:20170828103807j:plain

前作で、イーサン・ホークが演ずるアメリカ人青年ジェシーと、ジュリー・デルビーが演ずるフランス人女性セリーヌは、ブタペストからウィーンに向かう国際列車の中で出会う。ジェシーは次の日にウィーンからアメリカに帰国し、セリーヌはこの列車でそのままパリに帰ろうとしている。ウィーン中央駅に着いたときに、この街を一緒に散策しないかとジェシーセリーヌを誘う。意気投合した二人は、ウィーンの街を歩きながらひたすら会話を続ける。夜が明けて、パリに向かうセリーヌジェシーはウィーン中央駅で見送る。その時、二人は6か月後に再びこの場所で会おうと約束する。ここまでが前作のあらすじだ。

ウィーンで別れてから9年の歳月がたち、ジェシーはウィーンでのエリーヌとのロマンスを題材にして小説を書く。この小説のプロモーションのために、ジェシーはパリの書店で開催されたワークショップで作者として講演する。
f:id:bitterharvest:20170828104751j:plain
講演が終わろうとする頃、思いがけずエリーヌが入ってくる。
f:id:bitterharvest:20170828104959j:plain
ジェシーはその日の便で帰国しなければならないため、あまり時間が残されていない。それでも、コーヒーでも飲もうということで二人はカフェに向かう。前回と同様に、会話がずっと続く。その中で、再開を約束した場所に来たのかが話題になる。セリーヌジェシーが来なかったものと思いこんでいる。いや、そうあってほしいと思っている。セリーヌはブタペストのおばあさんが亡くなり、再会を約束したその日に埋葬されたので、とても残念だったが行くことはできなかったと自身の理由を説明する。さらに、でもあなたも来なかったのよねと言い、それには特別の理由があったはずだわと言ったあと、彼の表情を読み取って続ける。

“Oh...no! No, you were there, weren't you?”
「え、うそ。来たのね。そうでしょ。」

セリーヌはさらに慌てて、
“Oh, no, that's terrible!”
「それは大変だわ。」

心の動揺を抑えきれずに、
“I know I'm laughing, but I don't mean it!”
「笑ってるけど、そのつもりではないの。」

さらに続けて、
“Did you hate me? You must have hated me. Have you been hating me all this time? You have!”
「私のこと嫌ったでしょう。嫌いだったに違いない。私のことずっと嫌いだったでしょう。間違いないでしょう。」

ジェシーは、少し楽しみながら、否定する。
“No, no...”
「そんなことはないよ。」

セリーヌは慌てている様子を隠さずに、
“Yes, you have! Oh, but you can't hate me now, right? I mean, my grandma...”
「嫌ってたわよ。でも、今は嫌えないわよ。だって、おばあさんが…。」

ジェシーは会話を楽しみながら、
“I don't hate you, alright? Come on, it's no big deal, alright? I flew all the way over there, you blew the thing off, and then my life has been a big nosedive since then, but I mean it's not a problem.”
「嫌ってないよ。だって、大したことではないもの。再開を約束した場所へはるばると飛んできたんだ。そして、あなたが全てをぶち壊してくれた。それ以来、私の人生は急降下しているよ。でも、問題という訳ではないよ。」

セリーヌが本当に悪いことをしたという気持ちになって、
“No, you can't say that!”
「そんなこと言わないで。」

さらに続けて、
“Oh, I can't believe it, you must have been so angry with me... I'm so sorry, I really wanted to be there, more than anything in the world! I swear...Honestly, I swear...I mean, you can't be angry...my grandmother...”
「信じられないわ。あなたはずっと私に対して怒っているでしょう。本当にごめんなさい。世界中のどのようなことよりも優先して、そこに行けたらと本当に思っていたの。誓ってよ。本当に、誓ってよ。あなたは怒ってはいけないわ。だって、おばあさんが..。」

ジェシーはちょっと行き過ぎたかなともって、
“No, I know, I know, I honestly thought that something like that might have happened. I was definitely bummed, but...Mostly, I was just mad we hadn't exchanged any phone numbers or any information.”
「分かっているよ。そのようなことが起こったのだろうと本当に思ったよ。確かに落ち込んだよ。なぜ、電話番号か連絡先を交換しなかったのだろうととても悔やんだよ。」

40秒という短い会話だが、再会を果たせなかったことをお互いにとても悔やんでいる様子がこの会話に凝縮されている。二人はこのあと、もし再会できていたら人生は変わっていただろうと思いながら会話を続けていく。

さて、ジェシーは何事もなく帰国できただろうか。

この映画、軽快に会話がずっと続く。でも、一語一語しっかり聞こうとすると、会話にスピードがあってちゃんと把握するのが大変だということに気がつく。会話のリズムが心地よい映画だと納得する。

また、会話の部分には、'hate'という単語を、過去形、現在完了形、現在形に使い分けて、言い訳をしている。弁解をするときはこのようにしたらよいのだなととても参考になる。

通常のプログラムをHaskellで記述する(5)

子供の頃に喉から手が出るほどに欲しかったものを多くの人は覚えているだろう。それも自分の小遣いでは到底手が届かないほど高値のものを切望したのではないだろうか。デパートと言われるものが全盛だった頃、おもちゃ売り場は何とも楽しい場所だった。その中でも、動く鉄道模型は人気の場所だった。ジオラマという言葉はまだ使われていなかったので、なんと呼ばれていたのかは今となっては分からないが、線路を切り替えて機関車を思い通りに走らせることができるレイアウトはいつも子供たちで一杯だった。

そんな子供の時の夢をかなえるために、2年がかりでジオラマを作成した。孫にも一部手伝わせて、この夏やっと完成した。とりあえず、動画を楽しんで頂こう。

路線は外側の新幹線と内側のローカル線だ。線路は9mmの幅しかないけれども、4両編成の新幹線が脱線することもなく走行してくれる。新幹線も線路も精巧にできているのだなあと感心する。ジオラマは右側が里山、中央が都会、左側が下町という設定だ。広い場所を必要とするので、夏休み中だけ家族に公開している。

3.5 銀行のATMを完成させる

それでは、利息の計算まで含めてプログラムを完成することにしよう。状態の方は、利率\(i\)と現在高\(c\)のタプル\((i,c)\)となる。また、入力は、預金高\(d\)と前回の預け入れからの期間\(p\)のタプル\((d,p)\)となる。銀行口座を開設する関数\(initdep\)は入力の部分を新しいタプルに変えるだけなので次のようになる。

initdep :: (Floating a, Floating b, Floating c, Floating d) => (c, d) -> State (c, d) (a, b)
initdep (i,c) =  put (i,c) >>= \_ -> return (0,0)

それでは預金の関数\(deposit\)を作成しよう。これも、入力と状態のところを新しいタプルに変えるだけなので、次のようになる。

deposit :: (Floating a, Floating b) => (b, b) -> State (b, b) (a,a)
deposit (d,p) =  get >>= \(i,s) -> put ((i,s + d + i ** p)) >>= \_ -> return (0,0)

利用してみよう。開設時の預金額を500とし、利率を1.001としよう。そして5期間経過した後に30預金したとしよう。これは、開設時の関数\(initdep\)と預金の関数\(deposit\)を結合すればよいので次のようになる。

f = (\a -> initdep a) >=> (\_ -> deposit (30,5))
*Main> runState (f (1.001, 500)) (0,0) 
((0.0,0.0),(1.001,531.005010010005))

うまく動いているようだ。さらに、4期間経過した後に20預金したとしよう。これはさらに預金の関数\(deposit\)を結合すればよいので次のようになる。

*Main> g = (\a -> initdep a) >=> (\_ -> deposit (30,5)) >=> (\_ -> deposit (20,4))
*Main> runState (g (1.001, 500)) (0,0) 
((0.0,0.0),(1.001,552.009016014006))

大丈夫のようだ。
それでは、引出の関数\(withdraw\)を作成しよう。これは預金が加算であったのに対し、減算となるので次のようになる。

withdraw :: (Floating a, Floating b) => (b, b) -> State (b, b) (a,a)
withdraw (d,p) =  get >>= \(i,s) -> put ((i,s - d + i ** p)) >>= \_ -> return (0,0)

それでは、さらに6期間経過した後で50引出したとしよう。同じように次のようになる。

*Main> h = (\a -> initdep a) >=> (\_ -> deposit (30,5)) >=> (\_ -> deposit (20,4)) >=> (\_ -> withdraw (50,6))
*Main> runState (h (1.001, 500)) (0,0) 
((0.0,0.0),(1.001,503.015031034021))

これで基本的な部分は終了である。

\(initdep,deposit,withdraw\)がコマンドのように利用されているのが分かることと思う。これを強調するには糖衣構文を作成して、利用するとよい。Haskellでは\(do\)という構文が用意されている。
また、上記のプログラムをより洗練するためには、金額は通常は正の整数なのでそのための処理も加える必要がある。これについては、読者の方で試みて欲しい。

プログラムの全体は次のようになっている。

(>=>) :: (Monad m) => ( a -> m b) -> ( b -> m c) -> (a -> m c)
f >=> g = \a -> let mb = f a
                in mb >>= g

newtype State s a = State (s -> (a,s))

runState :: State s a -> s -> (a, s)
runState (State f) s = f s

get :: State s s
get = State (\s -> (s,s))

put :: s -> State s ()
put s = State (\_ -> ((), s))

instance Functor (State s) where
    fmap f (State g) = State (\s -> let (a, sa) = g s
                                    in ( f a, sa))

instance Applicative (State s) where
    pure a = State (\s -> (a, s))
    (<*>) mf ma = State (\s -> let (a, sa) = runState ma s
                                   (f, sb) = runState mf sa
                               in ( f a, sb))
instance Monad (State s) where
    ma >>= k = State (\s -> let (a, sa) = runState ma s 
                            in runState (k a) sa)
    return a = State (\s -> (a, s))

deposit :: (Floating a, Floating b) => (b, b) -> State (b, b) (a,a)
deposit (d,p) =  get >>= \(i,s) -> put ((i,s + d + i ** p)) >>= \_ -> return (0,0)

withdraw :: (Floating a, Floating b) => (b, b) -> State (b, b) (a,a)
withdraw (d,p) =  get >>= \(i,s) -> put ((i,s - d + i ** p)) >>= \_ -> return (0,0)

initdep :: (Floating a, Floating b, Floating c, Floating d) => (c, d) -> State (c, d) (a, b)
initdep (i,c) =  put (i,c) >>= \_ -> return (0,0)