読者です 読者をやめる 読者になる 読者になる

bitterharvest’s diary

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

Haskellで学ぶ圏論・ウォームアップ編 合コン

1.圏論とは

圏論の圏という単語は、どのような時に使われるのであろうか。合格圏とか不合格圏とか、模擬試験の成績を指標に判断された、受験生の時の苦い経験と結びつけて思い出す人もいる。東京あるいは東京寄りに住んでいる人は首都圏と結びつける可能性もある。宇都宮や高崎に住んでいる人たちは首都圏に属しているのかそうでないのかで迷うこともあるであろう。

このように、圏という単語は、範囲を定めるときに用いる。この定義を用いると、圏論とは「範囲を定めること」について論じる数学ということになる。しかし、この定義では、「どのようにして」範囲を定めるのかについて説明がなされていないので、何となく中途半端に投げ出されたようで、納得がいかない。そこで圏論を短い言葉で説明する時は、「どのようにして」の部分を強調する方がよいと思う。

いろいろな例を引っ張り出して「どのようにして」の部分を観察しようと思うが、取り敢えず、圏論とは「系の構造」を形式的に表す数学と定義することにする。

2.合コンの構造

男女が知り合う機会を増やすために、古今東西、様々な方法がとられてきた。かっては、合ハイというのもあったが、若者たちが健康的でなくなったのか、昨今は合コンである。この言葉は、合同のコンパ(コンパはドイツ語のKompanie、英語のcompany、あるいはフランス語のcompagnieなどからに由来)を短縮したもので、男性のグループと女性のグループがコンパを一緒に行うものである。

そこで、男性の参加者をm人とし、女性のそれをn人とする。mとnは同数の時もあるし、異なるときもある(あまり極端な開きが出ないようにするのが、合コンの幹事さんの重要な仕事であるが、ここではこのことは無視する)。

合コンをするからには、好みの人を探し、できればその人と付き合いたいと男性も女性も思っているはずである。そこで、合コンが終了したときに、出口調査ということではないが、男性の方からは可愛いと思う女性を必ず一人書いてもらうこととする。また、女性の方からは頼りになる(だいぶ古い考え方かもしれないので、気に入らない人はイケメンなどで置き換えてかまわない)と思う男性を、同じように、必ず一人書いてもらうこととする。

この出口調査によって、参加した男性と女性の(好意に関係する)構造がはっきりする。ここで、系は「合コン」ということになる。また、この系は、男性のグループと女性のグループという二つの集まりを有している。また、「可愛い」と「頼りになる」というこの集りの対応関係を表している。圏論では、集まりを「対象」、対応関係を「射」という。

系の構造を表すには図が一番である。そこで、合コンの構造を図で表すと次のようになる(下図ではm=3,n=4とした。即ち、男性3人女性4人としたが、これは例なので、この数字にとらわれる必要はない)。
f:id:bitterharvest:20150127093838p:plain

数学は形式化をするためにいくつかの制約を課している。合コンを考えるときにもいくつかの制約を課した。その一つが、出口調査で必ず一人の名前を書くことと断ったが、これは、関数が全関数となるようにするための制約である。

一般に、集合\(A\)から集合\(B\)への関数\(f: A \rightarrow B\)がどの元\(x \in A\)に対しても集合\(B\)の元が必ず一つ存在するとき\(f\)を全関数という。また、集合\(B\)の元が高々一つ存在する(存在しないときも許す)とき部分関数という。

図で示した構造を見ると、様々なことが見えてくる。相思相愛であったり、片思いであったり、可愛いと思っている女性がほかの男性を頼もしいと思っていたりする。例えば、可愛いと思っている女性がどの男性を頼もしいと思っているかを示す図は、上の図を下のように展開すると少し分かりやすくなる。
f:id:bitterharvest:20150127100305p:plain

この図から、真ん中の女性を削除して線のつながりだけを表すようにすると下図のようになる。
f:id:bitterharvest:20150127100831p:plain
この図を見るとこの合コンに参加したのが、よかったのか悪かったのかがはっきりするであろう。

3.Haskellで合コンの構造を表す

合コンの構造をHaskellのプログラムで表すと次のようになる。

module MatchmakingParty where

data Men = M1 | M2 | M3
  deriving (Eq, Ord, Show, Read, Bounded, Enum)

data Women = W1 | W2 | W3 | W4 
  deriving (Eq, Ord, Show, Read, Bounded, Enum)

cute :: Men -> Women
cute M1 = W3
cute M2 = W1
cute M3 = W2

reliable :: Women -> Men
reliable W1 = M3
reliable W2 = M2
reliable W3 = M1
reliable W4 = M2

合コン、即ち、Matchmaking Partyをモジュール名とし、対象である「男性のグループ」と「女性のグループ」をそれぞれ新たなデータ型MenとWomentで表した。また、それらの構成要素を定義した。男性はM1,M2,M3、女性はW1,W2,W3,W4である。また、射である「可愛い」と「頼りになる」をそれぞれ関数cuteとreliableで表した。また、それぞれの対応付けもした。

上記のプログラムを動かしてみる。M1がだれを可愛いと思ったかは次のようにしてわかる。

*MatchmakingParty> cute M1
W3

同様にW1がだれを頼もしいと思ったかは次のようにしてわかる。

*MatchmakingParty> reliable W1
M3

また、M1が可愛いと思った女性がだれを頼もしいと思ったかは、関数を合成し、それに値M1を入力すると得られる。

*MatchmakingParty> ( reliable . cute ) M1
M1

目出度く、相思相愛である。

それでは、自分を頼もしく思ってくれる女性(達)を求めることにする。これは、次の関数inverseReliableを用意することで可能になる。

inverseReliable :: Men -> [Women]
inverseReliable x = [ y | y <- [W1 .. W4], reliable y == x]

M2を頼もしく思ってくれる女性は次のようになる。

*MatchmakingParty> inverseReliable M2
[W2,W4]

モテモテである。しかし、自分が可愛いと思っている女性がこの中に含まれていないので残念と思うであろう。