bitterharvest’s diary

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

極限-HaskellでのReaderを定義する

3.2 \(Reader\)を定義する

Haskellでは\(Reader\)を用意している。Control.Monad.Readerというモジュールを読み込めば、使えるようになっている。しかし、このモジュールを理解しようとすると、忍耐力を必要とする。汎用性を高めるために、\(Reader\)が、\(ReaderT\)と呼ばれるデータ型を利用して、定義されているためだ。このため、\(Reader\)を理解しようとすると、別のいくつかのことを理解しなければならない。この作業は、煩わしく、下手をすると、何を理解しようとしていたのかさえ忘れてしまう。

そこで、ここでは、\(Reader\)の理解を助けるために、Haskellでの定義から離れて、必要な事項だけで説明することとしよう。

前回の記事で、\(Reader\)は

type Reader u a 

と理解して、利用した。これは、\(u\)という環境を与えて、\(a\)を出力するというものであった。\(Reader\)は、入力を\(u\)とし\(a\)を出力する関数を、データ型としたものと考えてよい(圏論では、データ型は対象である。関数を対象に選べるのも、圏論の汎用性、有用性を示す証左である)。そこで、次のように定義しよう。

data Reader u a = Reader (u -> a)

Haskellで用いられている用語の説明をしておこう。等式の左側に存在する\(Reader\)は型コンストラクタ(type constructor)と呼ばれる。また、\(u\)と\(a\)は型引数(type argument)と呼ばれる。\(data Reader \ u \ a\)により、データ型\(Reader\)は、データ型\(u\),\(a\)を用いて定義されていることを示す。

等式の右側の\(Reader\)は値コンストラクタ(value constructor)あるいはデータ・コンストラクタ(data constructor)と呼ばれる。これに続く\( \ u \rightarrow \ a\)は型と呼ばれる。そして、関数となっているので、特に、代数的データ型と呼ばれる。

上の定義を用いて、データ型\(Reader\)の値をいくつか求めて見よう。

Prelude> data Reader r a = Reader (u -> a)
Prelude> a = Reader $ \u -> 0.5 * u -- 数値を入力し、その半分を求める関数。もちろんa = Reader (*0.5)と入力しても同じ
Prelude> :t a
a :: Fractional a => Reader a a
Prelude> b = Reader $ \u -> show u – 数値などを入力し、その文字列を求める関数
Prelude> :t b
b :: Show a => Reader a String
Prelude> c = Reader $ \u -> show (u* u) – 数値を入力し、その2乗の文字列を求める関数
Prelude> :t c
c :: (Show a, Num a) => Reader a String
*Main> d :: Reader Int String ; d= Reader $ \u -> show ((*2) u) – 正数を入力し、その2倍の文字列を求める関数。これはd = Reader $ show . (*2)と同じ
*Main> :t d
d :: Reader Int String

1)ファンクタとしての定義

データ型が用意できたので、このデータ型を用いる関数を用意しよう。ファンクタから始めよう。

関手\(Reader\)は、与えられた関数を\(Reader\)というコンテナで包むものである。

データ型が用意できたので、このデータ型を用いる関数を用意しよう。ファンクタから始めよう。ファンクタでは、\(fmap \ f\)という関数を用意する必要がある。

圏\(\mathcal{C}\)は、関手\(Reader \)によって圏\(\mathcal{C’}\)に移されるものとしよう。そして、圏\(\mathcal{C}\)は、射の集まりで構成され、それらは\(U\)から\(X\)への射(\(r:U \rightarrow X\))としよう。また、任意の射\(r\)は、関手\(Reader\)によって圏\(\mathcal{C’}\)の射にコンテナをかぶせられた射\(Reader \ r\)に写されるものとしよう。

なお、コンテナをかぶせられた射は、関数\(runReader \ (Reader \ r) \ u\)を実行することにより、\(r(u)\)の値を出力する。
これらの関係を示すと下図になる。
f:id:bitterharvest:20180114104956p:plain
次に、圏\(\mathcal{C}\)内に別の射\(f\)が存在し、これは、射\(r\)を別の射\(s\)に写すものとする。このとき、\(s = f . r\)となる。また、\(f\)を関手\(Reader\)で写したものを\(fmap \ f\)としよう。これらから、次のような可換図式を得る。
f:id:bitterharvest:20180114105557p:plain
プログラムで示した例\(r =(*2),f=show\)の可換図式を求めると下図のようになる。
f:id:bitterharvest:20180114111313p:plain
それでは、Haskellでのファンクタの定義を示そう。

instance Functor (Reader r) where
  fmap f (Reader r) = Reader $ f.r

なお、ファンクタとして定義するとき、\(Reader\)が関手なので、\(r\)をつけずに、

instance Functor Reader where
  fmap f (Reader r) = Reader $ f.r

と定義しそうになるが、\(fmap\)の定義において、\(Reader\)ではなく\(Reader \ r\)を用いる必要があるので、\(r\)をつけないと誤りとなる。

2)モナドとしての定義

次はモナドでの関数を定義しよう。本論に入る前に、モナドがどのような数学的な概念であったかを復習しておこう。モナドとは、ある圏\(\mathcal{C}\)のモナド\(M\)とは、\(\mathcal{C}\)の対象\(A\)をコンテナ\(M\)で包んだものであり、それは\(M \ A\)と記述される。モナドには2つの関数が用意されていて、一つはモナドを作り出すもの、他の一つは、モナドからモナドを作り出すものである。二つの関数の用意の仕方にはいろいろあるが、Haskellでは\(return\)と\((>>=)\)を用意することになっている。それでは、下図を用いながら説明しよう。
f:id:bitterharvest:20180114111628p:plain

\(return\)は圏\(\mathcal{C}\)の対象\(A\)をモナドとしてのコンテナで包むことである。これを、\(return\)の型シグネチャで確認しよう。

:t return
return :: Monad m => a -> m a

例をいくつか挙げておこう。[ ] はモナドなので、整数から各括弧の付いたモナドを作成してみよう。

Prelude> a = return 3 :: [Int]
Prelude> a
[3]
Prelude> :t a
a :: [Int]

\(Maybe\)もモナドなので、整数から\(Maybe\)のモナドを作成してみよう。

Prelude> b = return 3 :: Maybe Int
Prelude> b
Just 3
Prelude> :t b
b :: Maybe Int

次の関数は、\((>>=)\)である。これは、二つの引数(\(M \ A,F\)))が与えられる。一つはモナドの値である。もう一つは関数である。この関数\(F\)は少し変わっていて、モナドにする前の値、即ちコンテナに包まれる前の値\(A\)を用いて、これをモナド\(M B\)に変換する。式で表すと、\(F: A \rightarrow M \ B\)である。型シグネチャで確認しておこう。

Prelude> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b

それでは、いくつかの例を見ていこう。まず各括弧の場合だ。\(f\)の関数は、整数が与えられたならば、それに4を加えて各括弧でくくることにしよう。次のようになる。

Prelude> a = return 3 :: [Int]
Prelude> f = \r -> [r + 4]
Prelude> c = a >>= f  -- 中置関数として
Prelude> c
[7]
Prelude> d = (>>=) a f  -- 前置関数として
Prelude> d
[7]

次は\(maybe\)の例を示そう。整数が与えられた時、それを2倍にし、モナド\(Maybe\)にして返す関数を考えよう。

Prelude> a = return 3 :: Maybe Int
Prelude> f = \x -> Just $ (*2) x 
Prelude> (>>=) a f
Just 6

モナドに慣れてきたので、\(Reader\)に対しても、\(return\)と\((>>=)\)を定義することとしよう。

まず、\(return\)から始めよう。次のように定義されている。

return x = Reader $ \u -> x

上の定義では、\(u\)の値に関わらず、\(x\)の値が定まるので、\(\backslash u -> x\)は定数関数となる。

いくつかの例を挙げてみよう。 \(return\)で出力値を与えて、\(runReader\)で実行するだけの簡単なものだ。

*Main> a = return 3 :: Reader Int Int
*Main> :t a
a :: Reader Int Int
*Main> runReader a 6
3
*Main> b = return 3 :: Reader String Int
*Main> :t b
b :: Reader String Int
*Main> runReader b "Three"
3
*Main> c = return "Jack" :: Reader String String
*Main> :t c
c :: Reader String String
*Main> runReader c "Betty"
"Jack"
*Main> 

次は、\(>>=\)である。モナドでの定義は次のようになっている。

*Main> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b

これをReaderで置き換えると次のようになる。

*Main> :t (>>=)
(>>=) :: Reader r -> return . s -> reader g

それでは、下図を参考にしながら、(>>=)を作成していこう。
f:id:bitterharvest:20180115092811p:plain

\( ( >>=)\)は基本的には、二つの関数の合成である。上の図であれば、\(Reader \ r\)と\(Reader \ s\)との合成である。\(Reader \ r\)を実行して、その出力を\(Reader \ s\)の入力として渡せばよい。入力となる値は、\(runReader (Reader \ r) \ u\)である。しかし、\(Reader \ s\)はこれを受け取れるようにはなっていないので、可能な形に変換する必要がある。それには、受け取った入力を\(s\)で変換し、それを戻す定数関数を作ればよい。これをしてくれるのは、先ほど示した\(return\)である。そこで、\(return . s\)とすればよい。従って、\(>>=\)への入力は、\(Reader \ r\)と\(f=return . s\)となる。

\(>>=\)からの出力は、\(Reader \ g\)である。そして、\(g\)は、入力を\(\backslash u\)とし、出力を\(runReader (f \ (runReader (Reader \ r) \ u)) \ u \)とする関数である。

従って、\(>>=\)は、\(Reader \ r\)を\(x\)で置き換えると次のように定めることができる。

x >>= f  = Reader $ \u -> runReader (f (runReader x u)) u

少し、用いてみよう。\(r=(*2),s=show\)の場合には、次のようになる。

*Main> a = Reader (*2) >>= return . show
*Main> runReader a 5
"10"

\(r=show,s=length\)の場合には、次のようになる。これは、入力した数字の桁数を求める関数である。

*Main> b = Reader show >>= return . length
*Main> runReader b 2018
4

最近のHaskellでは、モナドの上位クラスにアプリカティブが用意されている。従って、\(Reader\)と定義するためには、これも必要となる。ここでは、説明を省いて、アプリカティブを含めて、\(Reader\)に関連する定義を示そう。

import Control.Monad
import Control.Applicative

data Reader u a = Reader (u -> a)

instance Functor (Reader r) where
  fmap f (Reader r) = Reader $ f . r     

instance Applicative (Reader r) where
  pure x          = Reader $ \u -> x
  (Reader f) <*> (Reader x) = Reader $ \u -> (f u) (x u)

instance Monad (Reader r) where
 return x = Reader $ \u -> x
 x >>= f  = Reader $ \u -> runReader (f (runReader x u)) u

runReader :: Reader u a -> u -> a
runReader (Reader f) u = f u

ask :: Reader a a
ask = Reader $ \u -> u

メジナの香草焼き

お正月の料理にも飽きた正月8日に、例によって近くの超安売りスーパーに出かけた。我が家は、東京都に属しているのだが、遠くないところにある境川を越えると神奈川県になる。隣県側は製造関連の企業が多いことで知られていた地域だ。かつては、軒並み大きな工場が展開していたが、それらの跡地は大型のスーパーに代わっている。それでも、まだ、いくつかの大企業が残っていて、そこでは外国人の労働者がたくさん働いている。

スーパーで見かける彼らの言葉を聞いていると、南米の出身者だと分かる。中には、日本人と変わらない顔立ちの人たちも見かける。彼らの食習慣に合わせて、この大型スーパーでは、他では見かけないような大切りの肉が売られている。我々も、時々、とても大きなステーキ用の牛肉や、厚みのある豚ステーキ用の肉を購入している。

魚売り場にも、近海で取れたおいしそうな魚が、種類はそれほど多くはないが、時々売られている。この日は、いつもより多く、5種類を超えるほどの魚があった。その中に、体形の美しいメジナを見つけた。しかも、うれしいことに朝捕りで、とても新鮮だ。お刺身がおすすめだろうが、お正月料理が続いたので和食は食傷気味になっていた。もったいないような気もしたが、この日の夕飯を香草焼きで正月気分を一掃しようと考えた。

今回紹介するのは、その時のメジナの香草焼きだ。いつもの例に習って、材料たちに登場してもらおう。
f:id:bitterharvest:20180111095531j:plain

とてもシンプルだ。主材料は、もちろんメジナだ。背中からお腹にかけて幅のある魚だ。ウィキペディアで調べたら、スズキ目メジナ科となっていた。タイはスズキ目タイ科なので、お互いに親戚同士なのだろう。釣りをしないのでよく知らないのだが、釣人にとっては、人気の魚だそうで、「磯釣りの王様」と呼ばれている。

副材料は、魚の生臭さを消す役割も担わせて、玉ねぎ、トマト、ニンニクだ。その他に、ローズマリー、ハーブ入り岩塩、オリーブオイルだ。

メジナは鱗と内臓を取り除く。鱗はタイのそれと比較するととても柔らかい。タイの鱗を撮るときは大根を利用するが、メジナの場合には柔らかすぎて無理かもしれないので、包丁の刃先をなでるようにして、取り除いた。また、内臓からは肉のような塊が出てきた。食べた小魚が胃の中で消化の途中だったのだろう。
f:id:bitterharvest:20180111095600j:plain

玉ねぎ(1個)、トマト(1個)、ニンニク(2かけ)を細切りにする。
f:id:bitterharvest:20180111095637j:plain

次の作業は、岩塩の刷り込みだ。
f:id:bitterharvest:20180111095708j:plain

たまたま、旅行のお土産にもらったイタリア産のものがあったので、これを用いた。耐熱皿にメジナをのせ、まず片面にハーブ入り岩塩を小さじ半分程度刷り込み、ひっくり返して同じことをし、最後に、お腹にも刷り込む。

次の作業は野菜をのせることだ。最初に、お腹に、玉ねぎ、トマト、にんにくを入れる。
f:id:bitterharvest:20180111095754j:plain

野菜の残りを魚の上にのせる。
f:id:bitterharvest:20180111095824j:plain

200度にしたオーブンで30分ほど焼く。
f:id:bitterharvest:20180111095912j:plain

そして、食卓に供する。
f:id:bitterharvest:20180111095933j:plain

この日は、コーンスープも作った。美味しい西洋料理を楽しむことができ、正月気分から抜け出すことに成功した。

極限-HaskellでのReaderについて

3.Haskellでの極限と余極限

これまでの記事で、極限と余極限の説明をしてきた。数学的な記述が主で、Haskellを学ぼうとしている人は、役に立たないなと感じたことだろう。圏論での積や余積は、乗算や加算、あるいは、論理積論理和と関係があることは、直感でもわかる。しかし、これらのために、わざわざ圏論まで持ち出す必要はないと思われただろう。

そこで、今回は、日常的に使われるることはないが、Haskellの奥深さだけではなく、両者の繋がりを巧みに伝えてくれるHaskellの秘密兵器を紹介しよう。

3.1 \(Reader\)を理解しよう

今回、紹介する話題は\(Reader\)である。これまでも説明してきたので、理解されている方も多いと思うが、初めてという方もいることと思う。

\(Reader\)は、なかなか理解しにくいので、手始めにどのような機能を有していて、どのように利用されているかについて説明しよう。

Haskellでは\(Reader\)は次のように定義されている。

type Reader u = ReaderT * u Identity

この定義だと、\(ReaderT\)を理解することが必要になるので、手っ取り早く\(Reader\)を理解することはできない。そこで、上記の定義をとりあえず置いておき、次のように理解しておこう。

type Reader u a

ここで、\(u\)は環境と呼ばれるもので、\(a\)は環境から作り出される値である。少し、利用してみよう。

\(Reader\)には、\(return\)という関数が用意されているので、これを用いて\(Reader\)の値を作り出してみよう。

Prelude> import Control.Monad.Reader
Prelude Control.Monad.Reader> a = return 3.5 :: Reader String Double

それでは、\(return\)によって戻された値の型を確認しておこう。

Prelude Control.Monad.Reader> :t a
a :: Reader String Double

他にもいくつか試してみよう。

Prelude Control.Monad.Reader> b = return "A Happy New Year." :: Reader String String
Prelude Control.Monad.Reader> :t b
b :: Reader String String
Prelude Control.Monad.Reader> c = return 3 :: Reader Int Int 
Prelude Control.Monad.Reader> :t c
c :: Reader Int Int

\(Reader\)には、\(runReader\)という関数も用意されている。この関数は、\(Reader\)の値と、環境の値とを入力すると、\(Reader\)の2番目の型変数に対応した値を出力してくれる。まずは実行例を示そう。

Prelude Control.Monad.Reader> a = return 3.5 :: Reader String Double
Prelude Control.Monad.Reader> d = runReader a "Please, execute it."
Prelude Control.Monad.Reader> d
3.5
Prelude Control.Monad.Reader> :t d
d :: Double

当然、環境の値のデータ型が異なると実行されない。

Prelude Control.Monad.Reader> runReader a 3
<interactive>:22:13: error:
    ? No instance for (Num String) arising from the literal ‘3’
    ? In the second argument of ‘runReader’, namely ‘3’
      In the expression: runReader a 3
      In an equation for ‘it’: it = runReader a 3

\(runReader\)の型シグネチャは次のようになっている。

runReader :: Reader u a -> u -> a

1) 預金残高と利息

\(Reader\)の性格が分かってきたところで、一般的な使い方を示そう。これまで説明しなかったが、\(Reader\)はモナドである。従って、通常のプログラミング言語と同じように、逐次的に命令の列を用意することが可能である。多く用いられているのは、環境を入力して、それに基づいて出力するというものである。

環境を入力する関数として\(ask\)が用意されている。これを利用していくつかの例を示そう。最初の例は、年利率で2%、10万円の定期預金をした時に、\(r\)年後の残高を求めることにしよう。この例では、\(r\)が環境であり、残高が出力である。

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

import Control.Monad.Reader

amount :: Reader Int Double
amount = do
  year <- ask -- 何年間預金したかを入力する
  return (100000 * 1.02 ** (fromIntegral year)) --10万円預金したときの残高を出力

このプログラムを実行してみる。3年後の残高を求めてみよう。

Prelude> :load "amount.hs"
[1 of 1] Compiling Main             ( amount.hs, interpreted )
Ok, modules loaded: Main.
*Main> runReader amount 3
106120.79999999999

3年後には、6千円以上の利息が付いていることが分かる。今の銀行預金の利率もこのくらいならば、預金しがいもあるというものだ。

それでは、利率が3%になった時の比較をしてみよう。プログラムは次のようになる。

import Control.Monad.Reader

amount2 :: Reader Int Double
amount2 = do
  year <- ask -- 何年間預金したかを入力する
  return (100000 * 1.02 ** (fromIntegral year)) --2%の年率で10万円預金したときの残高を出力

amount3 :: Reader Int Double
amount3 = do
  year <- ask -- 何年間預金したかを入力する
  return (100000 * 1.03 ** (fromIntegral year)) --3%の年率で10万円預金したときの残高を出力

amount2vsAmount3 :: Reader Int String
amount2vsAmount3 = do
  a2 <- amount2                                 --2%の年率を実行
  a3 <- amount3                                 --3%の年率を実行
  return ( "2%: " ++ show a2 ++ " vs " ++ "3%: " ++ show a3)

上のプログラムに見るように、比較のプログラム\(amount2vsAmout3\)は、2%と3%のプログラム\(amoun2\)と\(amount3\)を実行させるだけだ。

さて、これを用いて4年間預けたときでの比較をしてみよう。

runReader amount2vsAmount3 4
"2%: 108243.216 vs 3%: 112550.881"

3%にはさらに魅力を感じることだろう。4年間預けておけば、利息だけで小旅行ができそうだ。

2)米国からドイツへ移動したときの単位の変換

\(Reader\)の使い方に慣れてきたが、さらに、ダメ押しでもう一つ例を上げてみよう。今度は、米国からドイツへ移動したときの単位の変換だ。

まず、変換のためのデータ型\(Conv\)を新たに用意しておこう。次のようにした。

data Conv = Conv

次にマイルからキロメートルへの変換のプログラムを作ろう。1マイルは1.6㎞なので次のようにする。

m2k :: Reader Conv String
m2k = do
  env <- ask
  return "One mile is equal to 1.6 km."

同様にポンドからキログラムへの変換プログラムを作ろう。1ポンドは0.45kgであるので、次のようになる。

p2k :: Reader Conv String
p2k = do
  env <- ask
  return "One pound is equal to 0.45 kg."

さらに通貨を変換してくれるプログラムを作ろう。1ドルは0.83ユーロとすると、次のようになる。

d2e :: Reader Conv String
d2e = do
  env <- ask
  return "One Dollar is equal to 0.83EUR."

最後にすべての変換を与えてくれるプログラムを作ろう。これは上記のプログラムを用いて次のようになる。

u2g :: Reader Conv String
u2g = do
  length <- m2k
  weight <- p2k
  money <- d2e
  return (length ++ " \n " ++ weight ++ " \n " ++ money)

それではこれを実行してみよう。

Prelude> :load "Reader.hs"
[1 of 1] Compiling Main             ( Reader.hs, interpreted )
Ok, modules loaded: Main.
*Main> runReader u2g Conv
"One mile is equal to 1.6 km. \n One pound is equal to 0.45 kg. \n One Dollar is equal to 0.83EUR."

このプログラムは、\(u2g\)というファイルを読みだしているようには見えないだろうか。このように、\(Reader\)には、データベースやファイルを読みだしているように感じさせる機能がある。

次回は、\(Reader\)を定義して、さらに理解を深めよう。

極限-余極限の例

2.2 余極限の抽象化

前回と同じように、余極限を抽象化してみよう。ここでは、下図のように、三つの圏を用意する。最初の圏\(\mathcal{C_0}\)は、余錐の頂点からなる圏だ。次の圏\(\mathcal{C}\)は余錐で構成される圏だ。最後の圏\([\mathcal{I,C}]\)はインデックス圏から余錐を構成したときの自然変換を射とする圏だ。
f:id:bitterharvest:20180105154344p:plain

今、圏\(\mathcal{C_0}\)で、対象\(C,C’\)の間の射は\(f:C \rightarrow C’\)であったとする。圏\(\mathcal{C_0}\)から圏\(\mathcal{C}\)には、ある関手によって、上図の中ほどのように写されたとする。同様に、圏\(\mathcal{C_0}\)から圏\([\mathcal{I,C}]\)には上図の右側のように写されたとする。

前回と同じように、圏\(\mathcal{C}\)と圏\([\mathcal{I,C}]\)の間では上図のように可換が成り立つ。従って、圏\(\mathcal{C}\)で余錐を与えると、圏\([\mathcal{I,C}]\)からそれはどのような性格を有しているのかを得ることができる。

上の図は、下のような可換図式に書き換えることができる。
f:id:bitterharvest:20180105154420p:plain

それでは、上の図を用いて、余極限のいくつかの例を挙げることにしよう。なお、例をあげるとき、対象\(C\)と余極限である対象\(ColimD\)とは一緒であるとする。

2.3 余極限の例

1)始対象

最初の例は、下図に示すように、余錐の上面が存在しない場合である。
f:id:bitterharvest:20180105154453p:plain

上面が存在しないので、圏\(\mathcal{C}\)では余錐は頂点だけからなる。また、余極限の余錐\(C=ColimD\)から任意の余錐\(C’\)に対して、一意的に定まる射\(m’\)が存在する。これを、圏\([\mathcal{I,C}]\)に写すと下図のようになる。これから、関手\(\Delta_C\)から任意の関手\(\Delta_C’\)への射が一意的に定まることから関手\(\Delta_C\)が始対象であることが分かる。

2)余積

それでは、余錐が独立した
2頂点で構成されている場合を考えよう。下図のようになる。
f:id:bitterharvest:20180105154554p:plain

圏\(\mathcal{C}\)では、2頂点の余極限の余錐は上図の左側のようになる。これに、任意の余錐を加えたのが真ん中の図である。これを圏\([\mathcal{I,C}]\)に写したのが右図である。\(\Delta_C\)から\(\Delta_{C’}\)への射が一意的に定まることから、下図に示すように余積となる。
f:id:bitterharvest:20180105154615p:plain

3) コイコライザ

それでは、2頂点と、その間を同じ方向に二つの射が結んでいるような余錐について考えてみよう。下図のようになる。
f:id:bitterharvest:20180105154638p:plain

錐の場合にはイコライザであったが、今回の場合はコイコライザになる。コイコライザの定義は次のようになっている。
「コイコライザの定義」適当な対象\(Q\)と射\(q:Y \rightarrow Q\)で\(q \circ f = q \circ g\)を満たすものが存在し、任意の対象\(Q’\)と射\(q’:Y \rightarrow Q’\)の組\((Q’,q’)\)で、\(q’ \circ f = q’ \circ g\)が与えられた時、射\(u:Q \rightarrow Q’\)が\(u \circ q=q’\)を満たすものが一意的に存在するとき、\((Q,q)\)の組をコイコライザという(下図参照)。
f:id:bitterharvest:20180105154724p:plain

4) 押し出し

最後は上面の頂点が3個あり、一つから他の二つの頂点へ射が与えられている場合だ。これは下図のようになる。
f:id:bitterharvest:20180105154944p:plain

これと双対の関係にあるものは、引き戻し(pullback)と呼ばれ、データベースを応用例として紹介した。
余極限の場合には、押し出し(pushout)と呼ばれ、共通のドメインを有する射の対が極限となる。

Puzzleと呼ばれるホームページに、押し出しを説明するのにちょうどよい例が上がっていたので、これを用いて説明しよう。
f:id:bitterharvest:20180105155727p:plain

ホームページには、鹿なのだろうか、2匹の小動物が、角をくっつけあって遊んでいる木工パズルが紹介されている。

小動物をそれぞれ\(A,B\)、くっつけあっている部分を\(Z\)とすると、上図のパズルが完成した様子は\(A \cup_f B\)と記述することができる。ここで、\(\cup_f \)は\(Z\)の部分で接合しているという意味である。なお、もう少し正確に説明すると、\(Z\)は\(B\)の部分集合で、接合される部分である。\(f:Z \rightarrow A\)は\(A\)の接合部分を求める関数である。\(f(Z)\sim Z\)は\(f(Z)\)と\(Z\)が同値であることを示すもので、これにより、接合部分がくっつけられたことを意味する。

接合部\(Z\)は、\(A\)と\(B\)のぞれぞれの部分となっている。\(Z\)から\(A\)と\(B\)への射がこれを表している。また、\(A\)と\(B\)は、パズルが完成したときの構造物\(A \cup_f B\)の一部となっているので、それぞれから射が存在する。

上記で用いたのはattaching functionと呼ばれるものである。これが押し出しの例になるということを示したが、この関数についてさらに知りたい人は、WikipediaでAdjunction spaceを参照するとよい。

次の記事では、Haskellでの極限と余極限の利用例を示そう。

極限-余錐と余極限の定義

2.余極限

極限と双対の関係にあるのが、余極限である。

2.1 余錐と余極限の定義

前回までの記事で、極限について説明してきた。極限は錐(cone)を用いることで定義した。即ち、ある圏の中で錐が定義できたとする。そのような錐は、複数あっても一つでも構わないが、「どの錐からも一意的な射が存在するようなが存在するとき、このを極限」と呼んだ。

双対は射の向きを反対にすることで得られる。極限の定理では、錐という専門用語を用いているが、余極限では、余錐(co-cone)という専門用語を用いる。錐は頂点(apex)から底面の方に向かって射が射影(projection)されていたのに対し、余錐は、底面の方から頂点に向かって射が射出(injection)される。余錐を用いると、余極限の定義は次のようになる。「どの余錐に対しても一意的な射が存在するような余錐が存在するとき、この余錐を余極限」と呼ぶことにしよう。

上記の言葉だけによる定義を、もう少し、明確にするために、インデックス圏を用いて定義することにしよう。下図のように、インデックス圏\(\mathcal{I}\)と圏\(\mathcal{C}\)が存在したとしよう。
f:id:bitterharvest:20180104103025p:plain

インデックス圏は、説明を簡単にするために、3対象とそれらの間の射および恒等射で成り立っているとしよう(これは一般性を失うものではない。もっと多くの対象が存在したとしても、3対象に分割して考えられることによる)。

圏\(\mathcal{I}\)から圏\(\mathcal{C}\)への関手に設けることにしよう。一つは、圏\(\mathcal{I}\)の全ての対象\(I,J,K\)を圏\(\mathcal{C}\)の同一の対象\(C\)に移す関手\(\Delta_C\)としよう。この関手は、圏\(\mathcal{I}\)の全ての射\(f,g,h\)を圏\(\mathcal{C}\)の対象\(C\)の恒等射に写すことに注意しておこう。

もう一つは、圏\(\mathcal{I}\)の3対象\(I,J,K\)を圏\(\mathcal{C}\)の別々の対象\(D_I,D_J,D_K\)に写したもので、これを関手\(D\)としよう。このとき、圏\(\mathcal{I}\)の射\(f,g,h\)は圏\(\mathcal{C}\)の射\(Df,Dg,Dh\)に移されたものとする。

\(\bf{余錐の定義}\)
関手\(F\)から関手\(\Delta_C\)への自然変換が存在するとき、\(D_I,D_J,D_K\)を面とし、\(C\)を頂点としたものを、余錐と呼ぶことにする。なお、錐の場合には、頂点を上に描いたが、余錐の場合には、頂点を下に描くことにする。従って、\(D_I,D_J,D_K\)によって作られる面は上に来るので、余錐の上面と呼ぶこととする。

\(F\)と\(\Delta_C\)による自然変換が存在するとは、上図では、
\begin{eqnarray}
\alpha_I = \alpha_J \circ Df \\
\alpha_J = \alpha_K \circ Dg \\
\alpha_I = \alpha_K \circ Dh
\end{eqnarray}
が成り立つことである。

\(\bf{余極限の定義}\)
圏\(\mathcal{C}\)内の任意の余錐に対して、ある余錐から一意的に定まる射が存在するとき、この余錐を余極限(colimit)と呼ぶ。

次の記事では、余錐の例を挙げるための準備をしよう。

極限-極限の例

1.8 錐の例

今年のブログの締めは、少しでも圏論が身近に感じられるようにするために、錐の例を取り上げよう。

前回のブログで、抽象度の高い、下図のような極限の可換図式を示した。
f:id:bitterharvest:20171228132358p:plain

この可換図式は、錐を作成すると、それがどのような極限なのかを、示してくれる。

上図で、圏\(C\)は、対象となっているのは錐だけで、射となっているのは錐の頂点間の写像という極めて簡素な圏である。

圏\([\mathcal{I,C}]\)はインデックス圏\(I\)から圏\(C\)への関手によって、錐がどのような構造を持っているかを示した圏である。

それでは、いくつかの例を示そう。

1)終対象

最初は、底面のない錐である。圏\(\mathcal{C}\)があった時、その対象は底面のない錐であったとしよう。その中には、極限と呼ばれる錐\(C’\)が存在する。これを\(LimD\)と記述しよう。これを下図の左側に示す。

そして、圏\(\mathcal{C}\)から任意の対象\(C\)を取り出そう。\(C\)も\(C’(=LimD)\)も錐であり、そして、\(C’\)は極限の錐であることから、\(m:C \rightarrow C’\)となる一意に定まる関数が存在する。そして、\(f:C’ \rightarrow C\)とした時、\(m= contramap \ f\)となる。これらの関係を下図の真ん中に示す。
これらの関係については、下図を参照のこと。錐の頂点は正確に記述すると\(\mathcal{C}(C',LimD)\),\(\mathcal{C}(C,LimD)\)だが、ここでは、簡略して\(C',C\)と記述している。
f:id:bitterharvest:20171221090801p:plain

これを圏\([\mathcal{I,C}]\)に移すと、下図の右側の図となる。これは、任意の対象について成り立っていることから、任意の対象\(\Delta_C\)から\(\Delta_{LimD}\)への射\(contramap \ f\)が存在することとなり、\(\Delta_{LimD}\)は終対象となる(なお、\(contramap \ f \)は圏\(\mathcal{C}\)と圏\([\mathcal{I,C}]\)で同一に記述しているが、構造は似ているものの異なる関数であることに注意しておこう)。

従って、頂点だけの錐は、極限が終対象となることが分かる。
f:id:bitterharvest:20171228132426p:plain

2)積、デカルト積、冪

次の例を示そう。次の圏\(C\)は、底面は有するが、2頂点だけで、辺を持たない錐を対象にしているものとする。それを、下図の右側に示す。

前回の例と同じように、錐\(C,C’\)を定めることにしよう。\(C’=limD\)は極限の錐である。これを示したのが、下図の左側と真ん中である。

そして、これを圏\([\mathcal{I,C}]\)に移してみよう。これは、圏\(\mathcal{C}\)の積であることが分かる。
f:id:bitterharvest:20171229095359p:plain

もう少し、分かりやすく示したのが下図である。
f:id:bitterharvest:20171228132508p:plain

底辺の頂点をさらに具体的にすると下図のようになる。底辺の頂点\(A,B\)が集合である時は、下図の右側に示すように、錐の頂点\(A \times B\)はデカルト積\((A,B)\)となる。

また、底辺の頂点\(X,Y\)を写像ドメインとコドメインと考えると、\(X \times Y\)は定数関数となり、冪\(Y^X\)で表される。(なお、\(X\)から\(Y\)への写像は、\(X\)の集合の要素の数を\(X\)とし、\(Y\)の集合の要素の数を\(Y\)とすると、定数関数の数は、\(Y^X\)となる。これを利用して、関数をこのように冪を用いて表現している)。
f:id:bitterharvest:20171228132529p:plain

3)イコライザ

さらに、例を示そう。次の圏\(C\)は底面に2頂点を有し、一方の頂点から他方の頂点へ二つの射\(f,g\)があるものとする。これを、下図の右側に示す。

前回の例と同じように、錐\(C,C’\)を定めることにしよう。\(C’=limD\)は極限の錐である。これを示したのが、下図の左側と真ん中である。
f:id:bitterharvest:20171228132612p:plain

これを、圏\([\mathcal{I,C}]\)に移すと上図の左側の図になる。

かつて、イコライザの説明をした時に、これを次のように定義した。

「イコライザの定義」適当な対象\(E\)と射\(eq:E \rightarrow X\)で\(f \circ eq = g \circ eq\)を満たすものの組\((E,eq)\)が存在し、任意の対象\(O\)と射\(m:O \rightarrow X\)の組\((O,m)\)で、\(f \circ m = g \circ m\)が与えられた時、射\(u:O \rightarrow E\)が\(eq \circ u = m\)を満たすものが一意的に存在するとき、\((E,eq)\)をイコライザという。

下図に示すように、圏\([\mathcal{I,C}]\)はイコライザの定義そのものである。従って、底辺の2頂点間で同一方向に二つの射が存在するとき、極限はイコライザとなる。
f:id:bitterharvest:20171228132642p:plain

4)引き戻し

さらに、例を示そう。次の圏\(C\)は底面に3頂点を有し、二つの頂点から残りの一つの頂点への写像が存在するものである。それを下図の右側に示す。
f:id:bitterharvest:20171228132709p:plain

この例はデータベースである。具体的に示そう。ある学年の名簿を作成したと仮定しよう。そして、上の図に示すように、錐の頂点はデータベースという対象である。ここには、男子学生、女子学生、組のテーブルがある。男子学生のテーブルには、名前を記載するフィールドと所属する組を示すフィールドがある。女子学生のテーブルも同じである。また、組のテーブルは、クラスの名前を記入する。

データベースからの射が、男子学生、女子学生、クラスと呼ばれる集合で、これらは錐の底辺での頂点となる。そして、頂点間では、男子学生と女子学生からクラスへの射が設けられている。

ここで、射の方向を変えて、クラスの側から男子学生あるいは女子学生を観察したらどのようになるであろうか。例えば、A組に属している男子学生を求めたとしたら、それは、{太郎、次郎、…}というように構成員の集まりとなる。通常、写像はコドメインとなっている集合の要素を与えてくれるが、この場合は、集合を与えてくれる。

このような場合、上図に示すように、男子学生からクラスへの写像の値が一致する男子学生の集合を表すために一本の線を引き、その線上に構成要素を記述する。これは、数学の用語では、ファイバーと呼んでいる。ホモトピーなどを学ぶときなどに、必要とされる概念である。

また、この錐の極限を、引き戻し、あるいはファイバー積という。

宿題:上記のデータベースを極限を用いてHaskellで実現しなさい。

年が明けたら、極限と双対関係にある、余極限について説明する。それでは、良いお年をお迎えください。

ジューシーなターキーをクリスマスに楽しむ

昨年、ブライン液に浸して、ジューシーなターキーを食べることができたので、今年も、これを利用することにした。ただし、昨年は、塩だけしか利用しなかった。砂糖も一緒に用いるとよいという情報も得ていたが、甘くなるのも嫌だなと思い、塩だけでブライン液を作った。

しかし、最近になって、砂糖を用いると水分がより吸収されるという記事を見たので、昨年とは異なるブライン液を作ることにした。

今年も昨年と同じ大きさのミニ・ターキーを仕入れた。
f:id:bitterharvest:20171225095350j:plain
成城石井に電話をして、確保したのが、このターキーである。お店の方で解凍してくれたので、料理する前の日まで冷蔵庫に保存しておき、最終の夜は冷たい家事室に移した。

今年も、孫たちが23日が都合がよいというので、イブのイブにターキーを食べることにした。朝8時から、ブライン液を作り始めた。水3リットルに対して、塩と砂糖をそれぞれ150g加えた。
f:id:bitterharvest:20171225095419j:plain
f:id:bitterharvest:20171225095439j:plain

バケツの中にビニール袋を二重にし、その中に、水、塩、砂糖を注入した。
f:id:bitterharvest:20171225095504j:plain

ターキーを袋から取り出すと、水が大量にこぼれる。これらの水は、本来、ターキーの中にあったものが、解凍に伴って流れ出てきたものだろう。ターキーの肉をぱさぱさにさせる要因だ。ターキーの重さを量ったら2.9Kgであった。
f:id:bitterharvest:20171225095552j:plain

これをブライン液の中に4時間ほど浸した。
f:id:bitterharvest:20171225095610j:plain

昼食後、ローストの作業に取り組んだ。ローストに使う材料は、以下の通りだ。
f:id:bitterharvest:20171225095631j:plain
ターキーに使う野菜は、臭い消しと出汁が主なので、手ごろな野菜を利用するのだが、今年はどの野菜も高く、屑野菜を用いたという気分にはならなかった。
野菜は、セロリ、ニンジン、キャベツ、玉ねぎ、パセリ、ローズマリーだ。さらに、ジャガイモを一緒に蒸かすことにした。

野菜を細かく切って、オーブン皿にもる(ジャガイモの姿も見えるが、これは、取り出して、後から、オーブンの中に入れた)。
f:id:bitterharvest:20171225095731j:plain

ブライン液から取り出したターキーはこのような感じ。
f:id:bitterharvest:20171225095907j:plain
重さをはかってみたら、3.0Kgであった。水分100gを吸ったことになる。昨年は、ブライン液の変化で吸われた水分の量を推定したが、正確ではなかったと思う。今年のほうが正しい量だ。
冷蔵庫に栗の瓶詰があったので、ターキーの内臓に栗を詰めた。
ターキーは、全身を塩胡椒して、オーブン皿にのせた。内臓から取り出した、首と砂肝も一緒にのせた。
f:id:bitterharvest:20171225095937j:plain

ターキーの上には、一箱のバターを手ごろな大きさに切ってのせた。
f:id:bitterharvest:20171225100050j:plain

オーブンを250度にし10分ほど焼いた。その後、温度を下げて焼く。低温の方がおいしく焼けるという記事を読んだので、去年より10度低くして、170度にした。ポップアップタイマー(写真の真ん中右上にある赤いもの)が上がってくるまで焼いた。これには、1時間40分要した。その間、20分おきぐらいに煮汁をターキーの上にかけた。なお、ジャガイモは、焼きすぎを避けるため、ターキーを焼き始めてから30分後にオーブン皿に加えた。

焼き上がりはこのような感じ。
f:id:bitterharvest:20171225100222j:plain

煮汁を利用して、ターキーにかけるスープを作る。濾した煮汁を鍋に移し、ローリエ一枚とマギーブイヨン一粒をくわえ、煮立ったところで、ウィスキー大匙一杯を加え、アルコールを飛ばして出来上がりだ。
f:id:bitterharvest:20171225100246j:plain
サラダやコーンスープやワインなどと一緒に、孫たちと一緒に5人で食した。
f:id:bitterharvest:20171225100457j:plain

ブライン液から出した後、ターキーは水洗いをしないで、そのまま用いたので、砂糖の甘みが心配であったが、だれも気にしなかった。
孫たちは成長期ということもあり、あっという間に食べられてしまったが、ジューシーで、とても美味しいターキーだった。

極限-錐と極限のさらなる抽象化

1.7 錐と極限のさらなる抽象化

前回の記事で、錐は二つの異なる方法で作成できることが分かった。一つは、錐の頂点から錐の底面への写像を自然変換で与えるものである。もう一つは、求める錐の頂点から極限の錐の頂点への射を与えるものである。

前回は、さらに、この二つの方法は同型の写像を与えることも示した。写像が同型であるので、この間で自然変換を定義できるようになる。求める錐の頂点を\(C\)としたとき、この始自然変換を\(\alpha_C\)で表すことにしよう。図で示すと次のようになる。
f:id:bitterharvest:20171221090641p:plain

ここまでが前回の話である。

それでは、この方法によって、\(C\)を頂点とする錐が得られたとする。この得られた錐から、別の錐\(C’\)を求めるにはどのようにしたらよいであろうか(下図)。
f:id:bitterharvest:20171221090658p:plain

なお、\(C\)と\(C’\)には、\(f:C’ \rightarrow C\)の関係があるものとする。ここで、\(f:C \rightarrow C’\)でないことに注意しておいてほしい。訳はすぐに分かる。

これの可換図式を求めると次のようになる。なお、関手は射も写像するが、その時移す側と移される側で向きが同じとき、この関手は共変関手(contravariant)と呼ばれる。それに対して、反対になるときは、関手は反変関手(contravariant)と呼ばれる。そこで、上の図では反変関手なので、\(f\)が移されている先を\(contramap \ f\)とした。
f:id:bitterharvest:20171221090723p:plain

上図の可換図式で\(\mathcal{C}(C,LimD)\)は射の集合であるので、それを\(u: C \rightarrow LimD\)と表すことができる。また、\(\mathcal{C}(C’,LimD)\)を\(v: C' \rightarrow LimD\)と表すことができる。ところで、\(f:C' \rightarrow C\)なので、\(v=u \circ f\)となる。

また、\([\mathcal{I,C}](\Delta_C,D)\)は自然変換である。従って、これはインデックス圏の対象\(I\)毎に、\(\mu_I:C \rightarrow D_I\)と表すことができる。同様に、\([\mathcal{I,C}](\Delta_{C'},D)\)を\(\nu_I:C’ \rightarrow D_I\)と表すことができ、先ほどと同様に、\(\nu_I =\mu_I \circ f\)となる。

この関係を示したのが下図である。
f:id:bitterharvest:20171221090801p:plain

この可換図式から、圏\(\mathcal{C}\)での頂点を\(C\)とする錐から、圏\([\mathcal{I,C}]\)での頂点\(C’\)の錐を求めるには、圏\(\mathcal{C}\)で\(C’\)に移動してから圏\([\mathcal{I,C}]\)にジャンプしてもよいし、圏\(\mathcal{C}\)から圏\([\mathcal{I,C}]\)にジャンプしてから\(C’\)に移動してもよいと言っている。これを図で表すと以下のようになる。
f:id:bitterharvest:20171221091405p:plain

極限の理論的な話はここまでだが、次回はいくつか例を示そう。

極限-錐と極限の抽象化

1.6 錐と極限の抽象化

前回の記事までで、インデックス圏を用いての粋と極限の求め方を説明してきた。その中では、インデックス圏から粋を作成しようとしている圏へ、三角形のまま移す関手と、一点にまとめる関手を用意した。前者は錐の底辺を形成し、後者は錐の頂点を形成することも説明した。また、インデクス圏に用意するものは三角形に限る必要はなく、多角形でもよいこと、さらには、それを無限とした円でもよいことを説明した。また、錐を構成するする条件として、全ての側面で可換であるということも説明した。

それでは、このようにして出来上がった錐をもう少し抽象化した件の中で考えることにしよう。

抽象化1

錐を作成するとき、インデックス圏\(\mathcal{I}\)と錐を構成する圏\(\mathcal{C}\)を用意し、その間を関手\(C,\Delta_C\)で結んだ。また、関手間に自然変換\(\alpha\)を定義した。

そこで、関手を対象とし、自然変換を射とすることで、新たな圏を定義することができる。これを圏\([\mathcal{I,C}]\)と呼ぶことにしよう。

抽象化2

もう一つは極限の錐を利用するものだ。圏\(\mathcal{C}\)の中に作られた錐を対象とし、それぞれの錐の頂点から極限の錐の頂点への写像を射とするものだ。これをそのまま圏\(\mathcal{C}\)としよう。ただ、それぞれの錐では、その側面が可換になっているということに注意しておこう。

この二つの抽象化を図で表すと次のようになる。
f:id:bitterharvest:20171219164902p:plain

直感的にこの二つは、同じであると感じであろう。左の方は、関手\(\Delta_C\)と\(D\)が与えられると、錐が形成されると説明している。右の方は、極限の錐の頂点\(LimD\)が与えられているとする。そして、ある対象\(C\)から極限の錐の頂点への射\(m\)が与えられたとき、その対象\(C\)は、錐の頂点になると言っている。従って、両方とも同じことを言っている。そこで、これをもう少し厳密にして、定理として示すことにしよう。

二つの抽象化は同型である

上の図を一般化して、下図のようにする。
f:id:bitterharvest:20171219164924p:plain

まず左側について説明する。\(\Delta_C\)と\(D\)の間の自然変換は、一般には、一つとは限らず複数となる場合もあり、集合となる。そこで、これを\([\mathcal{I,C}](\Delta_C,D)\)としよう。なお、自然変換がない場合もあるが、この場合には、錐を構成できないということになる。

次に右側を説明する。対象\(C\)から極限の錐の頂点\(LimD\)への射も、同じように一つとは限らず複数存在する場合もある(無の場合もあるが、この場合には錐を構成できないということになる)。この集合を\(\mathcal{C}(C,LimD)\)としよう。なお、\(C\)については錐であるという条件を課する必要はない。これは、後で分かるが、射がある場合には、必然的に、錐となる。

それでは、右側と左側は同型であることを示すこととしよう。

1) まず、左側から右側が導かれることを示す。これは、\([\mathcal{I,C}](\Delta_C,D)\)ならば\(C\)から\(LimD\)への射があることを示せばよい。

これは簡単である。関手\(\Delta_C\)と\(D\)によって錐を作成したとすると、その錐の頂点から極限の錐の頂点へ射\(m\)が存在することは、極限の錐の定義から明らかである。従って、\(m \in (\mathcal{C}(C,LimD)\)となるので、証明できたこととなる。

2) 次に、右側から左側が導かれることを示す。\(\mathcal{C}(C,LimD)\)であるならば、\([\mathcal{I,C}](\Delta_C,D)\)であることを示せばよい。

これには、射の集合\(\mathcal{C}[C,Limd]\)から任意の一つの射を取り出す。これを\(m\)としよう。このとき、\(C\)を頂点とする錐が構成できれば、証明できたことになる。これは、錐の辺が構成されることを、元々のインデックス圏の対象ごとに示せばよい。

下図に示すように、インデックス圏の対象\(I\)について考えてみよう。極限の錐にはその定義から射\(\beta_I\)が存在する。従って、\(m\)と\(\beta_I\)を合成したものは、射となるので、これを\(\alpha_I\)とする。これは、とりもなおさず、\(C\)を頂点とする錐の辺である。全てのインデックスの対象に対して、上記の操作を施すことで、\(C\)を頂点とした錐を実現することができ、証明は終わりである。
f:id:bitterharvest:20171219164943p:plain

極限-極限の定義

1.5 極限の定義

前回の記事で、インデックス圏から錐を作成する方法を示した。
f:id:bitterharvest:20171218102050p:plain

上図で、関手\(D\)によって、インデックス圏\(\mathcal{I}\)での三角形(頂点が対象、辺が射)が、圏\(\mathcal{C}\)に移され、これから作成される(三角)錐の底辺を形成する。この底辺の各頂点は\(\mathcal{I}\)の対象を、また、各辺は\(\mathcal{I}\)の射を、関手\(D\)によって、それぞれ移したものである。

また、上の図で、圏\(\mathcal{I}\)の三角形の頂点、即ち、対象の全てを、関手\(\Delta_C\)によって、一つの対象\(C\)に移した。このとき、圏\(\mathcal{I}\)の三角形の辺、即ち、射の全ては、\(\Delta_C\)によって、\(C\)での恒等射\(Id_{\Delta_C}\)に移される。

関手\(\Delta_C\)と関手\(D\)の間で、自然変換\(\alpha=\{\alpha_I,\alpha_J,\alpha_K\}\)が存在するなら、三角錐\(C,D_I,D_J,D_K\)が構成され、その側面は可換となっている。即ち、\(Df \circ \alpha_I = \alpha_J\), \(Dg \circ \alpha_J = \alpha_K\),\(Dh \circ \alpha_I = \alpha_K\)である。

同様に、関手\(\Delta_C’\)からも同じように側面が可換となっている三角錐を構成できる。

このような三角錐がいくつもできるであろう。その中で、極限と呼ばれるものを定義することにしよう。得られた三角錐の中から一つの頂点を選び、これを\(LimD\)と呼ぶことにしよう。\(LimD\)を頂点とする三角錐が次の条件を満たす時、極限という。なお、この三角錐での自然変換を\(\beta=\{\beta_I,\beta_J,\beta_K\}\)とする。

[条件] 任意の(三角)錐の頂点\(C\)に対して
1. 一意的に定まる射\(m: C \rightarrow LimD \)が存在し、
2. 圏\(\mathcal{I}\)の全ての対象\(i\)に対して、\(\beta_I \circ m = \alpha_I\)となる。即ち、上記の図の場合には、\(\beta_I \circ m = \alpha_I\),\(\beta_J \circ m = \alpha_J\),\(\beta_K \circ m = \alpha_K\)である。

説明では、理解しやすくするために、インデックス圏を三角形としたが、多角形でも構わない。さらには、辺の数が無限となった円でも構わない。

なお、このような射\(m\)は分解射(factorization)と呼ばれる。

また、\(\beta_I,\beta_J,\beta_K\)は、専門用語を用いれば、モノ射である。モノ射は次のように定義されている。射\(f:X \rightarrow Y\)がモノであるとは、任意の射\(g_1,g_2:Z \rightarrow X\)に対して、\(f \circ g_1= f \circ g_2\)であるならば、\(g_1=g_2\)が成り立つ。

極限-錐

1.4 錐

これまで、2回にわたって、圏論での極限の具体的な例を示してきた。そこでは、二つの対象\(A\),\(B\)とその極限\(A \times B\)ということで説明をした。また、極限は、ある条件を満たすものの中で最も良いものといういい方もした。また、ある条件を満たすものを候補とも説明した。

それでは、このような候補はどのようにして選ばれるのであろうか。あるいはさらに戻って、二つの対象はどのようにして選ばれるのであろうか。これらを選ぶ基準がないと、極限という概念を組み立てていくことができない。

そこで、ここでは、これらの選び方について説明することとする。

2対象からの錐

まず単純な例から説明しよう。二つの圏が与えられているとする。

一つの圏は、二つの対象\(1\),\(2\)しか有しない離散的な圏としよう(下図)。即ち、射は恒等射\(id\)しか有しないものとしよう。これを圏\(\bf{2}\)と呼ぶことにしよう。
f:id:bitterharvest:20171209202248p:plain

もう一つの圏を\(\mathcal {C}\)と呼ぶことにし、ここから二つの対象を適当に選び、これを\(A\),\(B\)にしたとしよう。そこで、圏\(\bf{2}\)からこれらの対象に関手\(D\)を張ることを考えよう。これは、
\begin{eqnarray}
A=D(1) \\
B=D(2) \\
id_A=D(id_1) \\
id_B=D(id_2)
\end{eqnarray}
となるような\(D\)が存在するならば、関手を張ることが可能である。ここで、\(id_1,id_2,id_A,id_B\)はそれぞれの対象での恒等射である。
f:id:bitterharvest:20171209202324p:plain
このような関手が張れたとしよう(上図)。そして、\(\mathcal {C}\)からもう一つ対象を選んできたとし、これを\(C\)としよう。これに対して、圏\(\bf{2}\)からこの対象に関手\(\Delta_C\)を張ることを考えよう。同じように
\begin{eqnarray}
C=\Delta_C (1) \\
C=\Delta_C (2) \\
id_{C}=\Delta_C (id_1) \\
id_{C}=\Delta_C (id_2)
\end{eqnarray}
となるような\(C\)が存在するならば、関手を張ることが可能である。ここでも満たしたとしよう(下図)。
f:id:bitterharvest:20171209202343p:plain
そこで、\(D\)から\(id_{C}\)への自然変換を考えよう。

自然変換

それでは、自然変換を復習しておこう。

下図に示すように、圏\(\mathcal{C}\)から圏\(\mathcal{C'}\)に対して関手\(D,D'\)が存在したとしよう。
f:id:bitterharvest:20171217084502p:plain
関手\(D\)から\(D'\)への自然変換\(Nat(D,D')\)とは、\(\mathcal{C}\)の任意の対象\(A,B\)に対して、上図が可換になることを言う。なお、\(A\)から\(B\)への射を\(f:A \rightarrow B\)とする。

上図は次のようになっている。
\begin{eqnarray}
D_A = D (A) \\
D_B = D (B) \\
D_f = D (f) \\
D'_A = D' (A) \\
D'_B = D' (B) \\
D'_f = D' (f)
\end{eqnarray}
である。

従って、可換は、\(\alpha_B \circ D_f = D'_f \circ \alpha_A\)を満たすこととなる。

圏\(\bf{2}\)からの自然変換

それでは、圏\(\bf{2}\)の自然変換を考えてみよう。(下図)。
f:id:bitterharvest:20171209202359p:plain
例えば、圏\(\bf{2}\)での対象1について考えよう。これは、\(D\)によって\(A\)に、\(\Delta_C\)によって\(C\)に写像変換されている。\(C\)から\(A\)への写像を\(\alpha_1\)とすると、これが自然変換を構成する要素となる。

対象2についても同様で、\(C\)から\(B\)への写像を\(\alpha_2\)とすると、これが自然変換を構成する要素となる。

なお、\(A\)と\(B\)の間には写像が存在しないので、可換の条件は存在しない。このため、\((\alpha_1,\alpha_2)\)は自然変換\(Nat(\Delta_C,D)\)となる。
一般には、自然変換は一つの組合せとは限らず、複数存在する。従って、可換を満たすものが\(n\)組ある場合には、\(Nat(\Delta_C,D)=\{(\alpha_1^1,\alpha_2^1),\{(\alpha_1^2,\alpha_2^2),...,\{(\alpha_1^i,\alpha_2^i)\}\)となる。

このようなものを選ぶことができるなら、\(C\)は\(A\)と\(B\)の積の極限への候補となる。

問題1:圏\(\bf{2}\)を利用して、二つの整数の公約数を選び出しなさい。
問題2:圏\(\bf{2}\)を利用して、料理作り好きな友人のリストの候補を作成しなさい。ヒント:知り合いを\(A\)とし、趣味を\(B\)を出発点に考えなさい。ここから絞っていくと、答えの一つとして、\(A\)は料理好きな友達の集まり、\(B\)は仏料理や和食のような種類の集まりを得る。

インデックス圏からの自然変換

圏\(\bf{2}\)をもう少し一般化してインデックス圏を用いてみよう。インデックス圏は、対象にインデックスが付加されており、対象間では射が定義されているものとする。ここでは、インデックス圏の中で最も単純な3つの対象からなるものを利用しよう。下図に示すように、インデックス圏\(\mathcal{I}\)と圏\(\mathcal{C}\)が存在したとしよう。
f:id:bitterharvest:20171209202420p:plain
圏\(\bf{2}\)の場合と同じように、\(\mathcal{C}\)から三つの対象\(D_I,D_J,D_K\)を選んだとしよう。これらには\(\mathcal{C}\)から関手\(D\)で張ることができたとしよう(下図)。
f:id:bitterharvest:20171209202434p:plain
即ち、前回と同じように次が満たされたとする。
\begin{eqnarray}
D_I=D(I) \\
D_J =D(J) \\
D_K=D(K) \\
Df=D(f) \\
Dg=D(g) \\
Dh=D(h) \\
id_{D_I}=D(id_I) \\
id_{D_J}=D(id_J) \\
id_{D_K}=D(id_K)
\end{eqnarray}

次に、\(\mathcal{C}\)から一つの対象\(C\)を選んだとしよう。これらには\(\mathcal{C}\)から関手\(\Delta_C\)で張ることができたとしよう(下図)。
f:id:bitterharvest:20171209202452p:plain
即ち、次が満たされたとする。
\begin{eqnarray}
C=D(I) \\
C =D(J) \\
C =D(K) \\
id_{C }=\Delta_C f =\Delta_C(f) \\
id_{C }=\Delta_C g =\Delta_C(g) \\
id_{C }=\Delta_C h=\Delta_C(h) \\
id_{C }=D(id_I) \\
id_{C }=D(id_J) \\
id_{C }=D(id_K)
\end{eqnarray}


ここで、関手\(\Delta_C\)から関手\(D\)に対して自然変換が成り立ったとしよう(下図)。
f:id:bitterharvest:20171209202511p:plain
自然変換は、ドメインとなった圏の対象ごと、ここではさらに射もあるので射ごとにも、ドメイン側の圏で、移されたものの間を射で結んだ時に、可換を保持しなければならない。これは、圏\(\bf{2}\)の時の説明と同じである。

このため、対象\(I,J,K\)に対して、射\(\alpha_I:C \rightarrow D_I, \alpha_I:C \rightarrow D_J,\alpha_I:C \rightarrow D_K\)が存在し、可換の条件を満たさなければならない。
f:id:bitterharvest:20171217090838p:plain
まず、射\(f\)に対しては、次のことが満たされなければならない(上図)。

即ち、
\begin{eqnarray}
\alpha_J = Df \circ \alpha_I
\end{eqnarray}

同様に射\(g\)に対して、
\begin{eqnarray}
\alpha_K = Dg \circ \alpha_J
\end{eqnarray}
が成り立ち、射\(h\)に対して、
\begin{eqnarray}
\alpha_K = Dh \circ \alpha_I
\end{eqnarray}
が成り立たなければならない。

この結果、下図に示すように、\(C\)を頂点として形作られた三角錐(\(C,D_I,D_J,D_K\))は、そのすべての側面において可換であるならば、自然変換である。即ち、\(\{(\alpha_I,\alpha_J,\alpha_K)\}\)は自然変換\(Nat(\Delta_C,D)\)の一つである。一般にはこのようなものは一つとは限らない。\(i\)個存在するとするならば、自然変換は\(Nat(\Delta_C,D)=\{(\alpha_I^1,\alpha_J^1,\alpha_K^1),(\alpha_I^2,\alpha_J^2,\alpha_K^2),...,(\alpha_I^i,\alpha_J^i,\alpha_K^i)\}\)である。
f:id:bitterharvest:20180319134109p:plain

今回は、3つの対象からなるインデックス圏を用いて三角錐を得た。インデックス圏の対象を増やしていくと三角錐は円錐へと近づいていく。圏論では、インデックス圏から得られるこのような物体を錐(cone)と呼んでいる。

極限の定義はこの錐を用いて定義できるが、その話は次回行う。

極限-例:最大公約数

1.3 最大公約数

前回の記事では、集合を利用して、圏論での積を説明した。また、積の普遍性についても説明した。これらをさらに進めると、極限になる。しかし、もう少し例を挙げて、極限の説明をするための準備をすることにしよう。

ここでは、集合から離れることにする。極限という言葉は使わないが、類似した概念は中学校の数学でも現れる。そう、最大公約数(GCD: greatest common divider)だ。二つの整数が与えられた時に、共通の約数で最大のものが最大公約数だ。

今、二つの整数360と420を選んだとしよう。このとき、二つの整数の共通の素数は、(2,2,3,5)である。従って、これらの中からいくつかを取り出して掛け合わせたものは公約数となる。例えば、(2,2,3)からの12、あるいは、(2,3,5)からの30などはこの二つの数の共通の約数である。また、全てを取り出した(2,2,3,5)からの60は最大公約数である。これらを\(X,X’,A \times B\)とし、360と420を\(A\),\(B\)で表すと、以下のような可換図式を得る。
f:id:bitterharvest:20171204143050p:plain
この図は、前回の記事で積の極限を説明したときの図と同じものである。この図より、\(A \times B\)が、\(A \)と\(B \)の積の極限、すなわち最大公約数、になっていて、\(X\)や\(X’ \)などが、\(A \)と\(B \)の積の候補、すなわち公約数、であることが分かる。従って、候補の中でもっともよいものが極限、すなわち、公約数の中で最も優れたもの、この場合には大きいものが最大公約数となっている。

即ち、上記の図において、\(A\)と\(B\)に対する任意の公約数\(X\)は、最大公約数\(A \times B\)に対して、一意的な射\(m\)が存在し、
\begin{eqnarray}
fst \circ m = p \\
snd \circ m =q
\end{eqnarray}
である。ここで、\(fst:A \times B \rightarrow A \),\(snd:A \times B\)である。これにより、最大公約数は圏での積である。

上記の図は、公約数で表したが、これを、それぞれを構成する素数で表すと次のようになる。
f:id:bitterharvest:20171204143115p:plain
この図で、公約数を、すなわち最大公約数の候補を、それを構成している素数の集合と見なすと、候補は、極限即ち最大公約数の部分集合となっていることが分かる。

これは、前回、集合と説明したときと同じで、その時も候補は極限の部分集合になっていた。このようにみていくと、最大公約数の場合も、前の例題と同じだということが分かる。

このため、個別に定義するのではなく、共通な概念として極限を考えたほうがよいということが分かる。

問題:最大公約数が作る圏をHaskellで作成しなさい。

コテージパイ - ひき肉料理をポテトでトッピングしたイギリス家庭料理

今日、紹介する料理は、イギリスの伝統的な家庭料理、コテージパイ(Cottage Pie)だ。ウィキペディアによれば、この名前が使われるようになったのは1791年で、このころ、ジャガイモが貧困層でも利用できるようになった。

ジャガイモは、ペルー南部のチチカカ湖畔が発祥とされている。ヨーロッパに伝わったのは1570年ごろで、スペイン人が持ち込んだ。その普及は緩やかだったようで、本格的にヨーロッパで栽培されるようになるのは18世紀半ごろ、栽培の推進をしたのはプロイセン王のフリードリッヒ大王である。また、同じころ、アイルランドでは小作農家がジャガイモの栽培を行うようになり、急激にその依存度を高くした。おそらく、この時期に、ジャガイモを利用したコテージパイが食卓に上がるようになったのであろう。

コテージパイはいたって調理が簡単な料理だ。ひき肉を玉ねぎとにんじんと一緒に炒め、その上にマッシュポテトをトッピングして、オーブンで温めるだけだ。料理に使う材料は以下のものだ。
f:id:bitterharvest:20171127094524j:plain

主なものは、牛ひき肉(300g)、ジャガイモ5個、玉ねぎ1個、ニンジン1本だけ、残りは味付け用なので、好みに応じて変えてもよい。

最初に用意するのは、マッシュポテト。ジャガイモの皮をむき、
f:id:bitterharvest:20171127095134j:plain

大きさが均等になるように、1個のジャガイモをそれぞれ12等分する。
f:id:bitterharvest:20171127095426j:plain

今回は、これらをラップして、電子レンジの「茹で根菜」という機能を利用して、調理した。
f:id:bitterharvest:20171127172209j:plain

中まで火が通っていれば、ラップの上に厚い布をかぶせ、指で押せば、マッシュポットができる。今回は、少し硬かったので、中華料理のレンゲの底で押してつぶした。
f:id:bitterharvest:20171127172915j:plain

つぶしている途中で、牛乳大匙2杯、バター10g、塩、黒胡椒をそれぞれ小さじ1/4を混ぜ、マッシュポテトに味付けをする。

玉ねぎ1個とにんじん1本はそれぞれみじん切りにする。
f:id:bitterharvest:20171127172836j:plain
f:id:bitterharvest:20171127172853j:plain

フライパンを温め、オリーブ油をひいて、牛ひき肉を色が変わるまで炒める。
f:id:bitterharvest:20171127173242j:plain
さらに、玉ねぎを混ぜて、これが透明になるまでさらに炒める。
f:id:bitterharvest:20171127173345j:plain
塩小さじ1、黒胡椒を加え、さらにローリエ、ニンジンを加えて、1分ほど炒めた後で、80ccのお湯にマギーブイヨン1個を溶かし、これを加える。
さらに、薄力粉大匙2杯を茶こしを使ってまんべんなくまぶし、トマトペースト(6倍濃縮)を一袋(18g)加えて、水分がなくなるまで、さらに炒める。
f:id:bitterharvest:20171127173636j:plain
にんじん、玉ねぎと一緒に炒めたひき肉を、耐熱皿に移し、平らにする。
f:id:bitterharvest:20171127173854j:plain
その上に、マッシュポテトをのせる。
f:id:bitterharvest:20171127173956j:plain
190度に熱したオーブンで、これを20分間ほど温める。
f:id:bitterharvest:20171127175240j:plain
野菜を付け合わせにして、食卓に出す。今回はインゲンにした。
f:id:bitterharvest:20171127175431j:plain
f:id:bitterharvest:20171127175401j:plain

コテージパイの断面はこのようになっている。
f:id:bitterharvest:20171127175638j:plain

年末の忙しい時期には料理にあまり時間をかけられないので、手間のかからないコテージパイは手ごろな料理である。

今回は、ひき肉に牛を用いたが、イギリスではラムやマトンを用いることもある。この場合には、シェパーズパイ(shepherd's pie)と呼ばれる。トライしてみたいのだが、ラムのひき肉が入手しにくいのが問題だ。

極限-圏論の積

プログラマのための圏論(初級編)では、自然変換まで説明した。ここまで理解すると本当の意味で圏論を自由に扱えるようになる。上級編では、これまでの理解を踏まえて、さらに圏論の奥義を学ぶことにしよう。

1.極限

圏論の特徴は抽象階層だと思う。圏は、対象と射によって構成される構造だ。従って適当に、対象と射を選ぶことによって、圏を作ることができる。下図では、圏\(\mathcal{B}\)は、対象\(A,A’\)と射\(f,f’,f’’\)により構成されている(圏を構成するには、このほかに、合成や恒等射などを必要とするがここでは本質的なものだけで記述する)。

さらに、圏を対象にして、圏と圏との関係を射とすることで、抽象的な圏を作成することができる。この操作を繰り返すことで、より抽象的な圏を得ることができる。

下図では、圏\(\mathcal{B}\)を対象\(B\)にして、新たな圏\(\mathcal{C}\)を構成した。\(B’\)は同じく圏\(\mathcal{B’}\)を対象にしたものである。\(g,g’,g’’\)は圏\(B\)と\(B’\)の間の射である。一般には、\(g,g’,g’’\)は関手と呼ばれ、\(\mathcal{C}\)は小さな圏の圏と呼ばれる。

同じように、圏\(\mathcal{D}\)も構成される。この時、\(h,h’,h’’\)は自然変換と呼ばれる。
f:id:bitterharvest:20171125085355p:plain

逆に、ある圏から、その対象の要素を対象とし、要素間の関係を射とすることで、具体的な圏を作成することができる。この操作を繰り返すことで、より具体的な圏を得ることができる。

対象と射という概念で、抽象階層のどのレベルをも構成できるため、圏の構造はとても規則的で、簡潔であると言える。

圏論では、あらゆる種類の中で成り立っているような普遍的な性質を表現することを一つの目標とする。圏論の教科書を開くと様々な普遍性を見つけることができる。その中で、抽象階層の有用性を教えてくれる普遍性は極限だと思う。中学校では、最大公倍数や最小公倍数などを習ったし、高校では関数の最大値・最小値や無限数列の極限値などを学んだ。これらは、ある性質を有するものの並びの中で、極限にあるものを求めている。

それでは、圏論での極限がどのようなものであるかを見ていこう。極限の説明は、圏での積を用いて行われていることが多いので、ここでも、積を用いて説明しよう。

1.1 圏での積

圏論は、対象を定義しなければならない、ここでは、まず、\(A\)と\(B\)を対象としよう。そして、この積を\(A \times B\)で表すことにしよう。次に、射を定義することにしよう。ここでは、\(A \times B\)から\(A\)への射\(fst\)と\(A \times B\)から\(B\)への射\(snd\)とで表すことにしよう。図で表すと次のようになる。
f:id:bitterharvest:20171125085448p:plain

\(A\)と\(B\)が集合の場合には、積はデカルト積と呼ばれ、それぞれの要素\(a \in A\)と\(b \in B\)の対(a,b)で表すことができる。対として表した時、最初の要素が\(A\)に、二番目のそれが\(B\)に属すという意味で、分かりやすくするために便宜的に、射\(fst\)と\(snd\)を用いた。このため、\(fst\)と\(snd\)である必然性はないので、一般的によく用いられている\(\pi_1\)と\(\pi_2\)であってもよい。

圏で用いられている対象、射、積を漫然と理解したままで次に進むと罠にはまってしまうことが多いので、ここでは、これらの概念を具体的な例を用いて、より詳しく理解することにしよう。

圏での積は、乗算であったり、論理積であったりするが、ここでは、論理積と考えることにしよう。また、対象は、連続的な空間であったり、有限の要素の集合であったりするが、ここでは、まず、有限な要素の集合とする。そして、次のような問題を考えることにしよう。

例題1

「ある学年での\(A\)組のクラスで体育会系の部に属していた男女のペアそれぞれについて、同じ部に属していたかどうかを弁別する」プログラムを考え、先の対象\(A \times B\)を何にしたらよいかを考えることにしよう。

このプログラムは、条件「\(A\)組のクラスで体育会系の部に属していた男女のペア(これは、単一でも複数であってもよいとする)」を満たすもののみ受け付けることでき、そうでない場合には、受け付けず処理を行わないものとする。プログラムが受け付けた場合、同一の体育会系の部に属している場合には\(True\)を、異なる体育会系の部に属している場合には\(False\)を返すものとする。そして、プログラムが受け付けてくれるものを\(A \times B\)の候補ということにしよう。

例えば、\(A\)組テニス部所属\(B1\)君と\(A\)組水泳部所属\(G1\)さんの\(P1=(B1,G1)\)をプログラムに入力したとしよう。二人とも\(A\)組に属し、体育会系の部に属するので、プログラムは受け付けてくれ、\(False\)が返ってくる。従って、\(p1\)は\(A \times B\)の候補である。

次の例はどうであろうか。\(B\)組所属の男子\(b2\)と\(A\)組テニス部所属の女子\(G2\)の対\(P2=(B2,G2)\)をプログラムに入力したとしよう。男子が\(A\)組でないので、このプログラムはこの入力を受け付けない。このため、\(P2\)は候補とならない。

それでは、\(A\)組卓球部所属の男子\(B3\)と\(A\)組ダンス部所属の女子\(G3\)の対\(P3=(B3,G3)\)をプログラムに入力したとしよう。この入力は受け付けられる。このため、\(P3\)は候補となる。

このようなことを繰り返し行ったとすると、いくつもの候補が上がるであろう。その中で、不足することなく条件に合う対となっているのはどれであろうか。\(A\)組体育会系の部に所属する男子\(Bas\)と\(A\)組体育会系の部に所属する女子\(Gas\)の対であることは容易に分かる。

これを図で表してみよう。\(P1\)と\(P3\)と\(Bas \times Gas\)が候補であり、\(A \times B = Bas \times Gas\)が条件を満たす最大の集合であることが分かったので、次の可換図式を得る。図において\(incl\)は包含関数である。
f:id:bitterharvest:20171125085545p:plain

この例で、\(A \times B \)の候補となるのは、\(Bas \times Gas\)の部分集合であることが分かる。

例題2

先の例は離散系であったので、今度は連続した空間での例を挙げることにしよう。ある地域\(R\)の標高と年間平均気温の関係を表すことを考えよう。今、標高の方は赤色で表すことにし、高いほど濃くなるようにした。また、気温の方は黄色で表すことにし、低いほど濃くなるようにした。これらの色は絵の具で混ぜることにした。従って、標高が高く気温が低いほど、橙色は濃くなり、反対の場合には薄くなる。

標高を赤色で表した地域\(R\)の地図を\(A\)とし、年間平均気温を黄色で表した\(R\)の地図を\(B\)とした時、このような地図をその一部でも作成できるようなものを探すこととしよう。前の例に習って、これを\(A \times B\)の候補と呼ぶことにしよう。

\(R\)内のある地点\(R1\)での標高を\(P1_h\)とし、その地点での年間平均気温を\( R1_t\)とした時、\(R1=(R1_h, R1_t\)は、求められている地図の一部を描くことができるので、候補となる。

\(R\)の隣の地域\(R2\)での標高を\(R2_h\)とし、そこの年間平均気温を\( R2_t \)とした時、\(R2=(R2_h, R2_t)\)は、求められている地図の範囲外であるので、候補とはならない。

\(R\)に含まれる小さな地域\(R3\)での標高を\(R3_h\)とし、そこの年間平均気温を\( R3_t \)とした時、\(R3=(R3_h, R3_t)\)は、求められている地図の一部を描くことができるので、候補となる。

\(R\)に含まれる小さな地域\(R4\)での標高を\(R4_h\)とし、\(R\)内の別の地域\(R4’\)の年間平均気温を\( R4’_t \)とした時、\(R4=(R4_h, R4’_t)\)は、求められている地図の一部を描くことができないので、候補とならない。

\(R\)に含まれる小さな地域\(R5\)での標高を\(R5_h\)とし、\(R5\)の年間日照時間を\( R5_s \)とした時、\(R5=(R5_h, R5_s\)は、求められている地図の一部を描くことができないので、候補とならない。

これらの関係を可換図式で示したのが、下図である。
f:id:bitterharvest:20171125085613p:plain

この例でも、\(A \times B \)の候補となるのは、\(R_h \times R_t\)の部分集合であることが分かる。

1.2 積の定義

圏では積は次のように定義される。

\(\mathcal{C}\)を適当な対象\(A,B\)を有する圏とする。\(A\)と\(B\)の積は、\(A \times B\)と書かれる\(\mathcal{C}\)の対象と二つの射\(fst : A \times B \rightarrow A \)および\(snd : A \times B \rightarrow B \)との組で、以下の普遍性を満たすものをいう。

積の普遍性

任意の対象\(X\)(これは例題1,2では候補と呼んでいたもの)および射の対\(p:X \rightarrow A\)および\(q:X \rightarrow B\)が与えられた時、一意的な射\(m : X \rightarrow A \times B\)が存在して、下図
f:id:bitterharvest:20171125085657p:plain
を可換にする。

上の定義から、この圏では、\(A\)と\(B\)への射を有するどのような対象を持ってきたとしても、積の普遍性が満たされる。即ち、\(A\)と\(B\)への射\(p'\)と\(q'\)を有する任意の対象\(X’\)を持ってきたとしても下図のように可換性が成り立ち、一意的な射\(m’ : X’ \rightarrow A \times B\)が存在する。
f:id:bitterharvest:20171125085922p:plain

このことから、このような全ての対象(例題1,2で候補と言っていたもの)の中で、\(A \times B\)が\(A\)および\(B\)への最も優れた射(射の合成として表されないという意味で優れたということにする)を与えることから、極限ともいわれる(ただし、極限はのちの説明ではもっと一般的に使う。候補の中で、どれよりも優れた射を有するものと理解して欲しい)。

理解を深めるためには、次の問題を解くことを勧める。

問題1:例題1をHaskellで実現しなさい。
問題2:例題2をHaskellで実現しなさい。

縄文時代のモラルと家族システム

神奈川歴史研究会の9月の例会で発表した報告書を転載します。

縄文時代のモラルがどのように形成され、どのような家族システムを構築したかについて論じています。