---
title: Haskellと圏論：パフォーマンス改善からKan拡張へ
tags: 
author: [グミ](https://image.docswell.com/user/GummyCandy1206)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/4JMY3DKMJW.jpg?width=480
description: Haskellと圏論：パフォーマンス改善からKan拡張へ by グミ
published: July 11, 26
canonical: https://image.docswell.com/s/GummyCandy1206/ZN7X7P-2026-07-11-kan-extension
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/4JMY3DKMJW.jpg)

Haskell と圏論：
パフォーマンス改善から Kan 拡張へ
グミ@GummyCandy1206
関数型まつり 2026 2026-07-11
#fp_matsuri_b
1 / 67


# Page. 2

![Page Image](https://bcdn.docswell.com/page/PJR9Q4XL79.jpg)

自己紹介
グミ @GummyCandy1206
• 富山県のエンジニア
• 好きな言語: Haskell, Lean
• 趣味で関数型と圏論を勉強しています。
• 仕事でも関数型使いたい！
最近は圏論の Kan 拡張と Haskell の関係について勉強していまし
た。この発表ではそのことについて話します。
2 / 67


# Page. 3

![Page Image](https://bcdn.docswell.com/page/PEXQ52M6JX.jpg)

Haskell は圏論に由来するいくつかの概念を取り入れている。
例えば…
圏論における、対象と射
Haskell における、型と関数
id𝐴
id
𝐴
a
𝑓
id𝐵
f
𝑔∘𝑓
𝐵
id
𝑔
g . f
b
g
𝐶
c
id𝐶
id
3 / 67


# Page. 4

![Page Image](https://bcdn.docswell.com/page/3EK96MGGED.jpg)

もちろん、それだけではなく…
圏論における、Functor
𝐹 id𝐴
Haskell における、Functor
𝐹𝐴
f a
𝐹𝑓
𝐹 id𝐵
fmap f
𝐹 (𝑔 ∘ 𝑓)
𝐹𝐵
fmap id
fmap id
𝐹𝑔
fmap (g . f)
f b
fmap g
𝐹𝐶
f c
𝐹 id𝐶
fmap id
4 / 67


# Page. 5

![Page Image](https://bcdn.docswell.com/page/L73W6YN575.jpg)

他にも…
圏論
Haskell
自然変換𝛼 : 𝐹 ⇒ 𝐺
多相関数 forall a. f a -&gt; g a
モナド(𝑇 , 𝜂, 𝜇)
Monad m
5 / 67


# Page. 6

![Page Image](https://bcdn.docswell.com/page/87DKV5WYJG.jpg)

一方で、圏論には次の有名な言葉がある。
We end with the observations that all concepts of category
theory are Kan extensions.
— Mac Lane, Saunders. Categories for the Working
Mathematician.
圏論におけるすべての概念は Kan 拡張！
6 / 67


# Page. 7

![Page Image](https://bcdn.docswell.com/page/VJPKVG92E8.jpg)

圏論は Haskell に影響を与えている。
Haskell
影響
圏論
7 / 67


# Page. 8

![Page Image](https://bcdn.docswell.com/page/2EVVZ6MXEQ.jpg)

一方で、圏論におけるすべての概念は Kan 拡張である。
Haskell
影響
圏論
すべての概念
8 / 67
Kan 拡張


# Page. 9

![Page Image](https://bcdn.docswell.com/page/57GL4NGREL.jpg)

では、Haskell の概念も Kan 拡張として理解できるのでは？
Haskell
?
影響
圏論
すべての概念
9 / 67
Kan 拡張


# Page. 10

![Page Image](https://bcdn.docswell.com/page/4EQYGQXYJP.jpg)

“Haskell Kan extension”で調べてみると、なんと Kan 拡張に関する
Haskell のパッケージが見つかる！
参考：https://hackage.haskell.org/package/kan-extensions
10 / 67


# Page. 11

![Page Image](https://bcdn.docswell.com/page/KJ4W5N6Z71.jpg)

この発表のゴール
kan-extensions パッケージのコードを通じて、
Haskell と Kan 拡張の関係を理解する。
11 / 67


# Page. 12

![Page Image](https://bcdn.docswell.com/page/LE1YW5VD7G.jpg)

Data.Functor.Kan.Ran に右 Kan 拡張が定義されている。
1 newtype
2
Ran g h a
= Ran { runRan :: forall b. (a -&gt; g b) -&gt; h b }
12 / 67


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GEWG65L8J2.jpg)

1 newtype
2
Ran g h a
= Ran { runRan :: forall b. (a -&gt; g b) -&gt; h b }
一見しただけでは
• どのように利用できるのかがわからない
• 圏論の右 Kan 拡張との関係が分からない
kan-extensions の中でも簡単で具体的な例から徐々に一般化して
Haskell と Kan 拡張の関係を観察する。
13 / 67


# Page. 14

![Page Image](https://bcdn.docswell.com/page/47ZLYNM9J3.jpg)

Yoneda
14 / 67


# Page. 15

![Page Image](https://bcdn.docswell.com/page/YJ6WD8NDJV.jpg)

次のようなコードを考える。
1
import Debug.Trace
2
3
data Box a = Box [a] deriving Show
4
5
6
instance Functor Box where
fmap f (Box xs) = trace &quot;重い処理&quot; $ Box (fmap f xs)
7
8
9
g :: Int -&gt; Int
g x = x + 1
10
11
12
13
14
15
plain :: Box Int
plain = fmap g $
fmap g $
fmap g $
Box [1,2]
つまり、fmap が重い場合を考える。
（Box は説明用に定義した Functor）
15 / 67


# Page. 16

![Page Image](https://bcdn.docswell.com/page/GJ5M3958J4.jpg)

このコードの実行結果は以下の通り。
1 ghci&gt;
plain
2 重い処理
3 重い処理
4 重い処理
5 Box [4,5]
重い処理が 3 回呼び出されている。
16 / 67


# Page. 17

![Page Image](https://bcdn.docswell.com/page/LE3W6YNGE5.jpg)

先程のコードの plain を次のように修正する。
1
import Data.Functor.Yoneda
2
yoneda :: Box Int
4 yoneda = lowerYoneda $
5
fmap g $
6
fmap g $
7
fmap g $
8
liftYoneda $
9
Box [1,2]
3
kan-extensions の Data.Functor.Yoneda で定義された関数を利用する。
17 / 67


# Page. 18

![Page Image](https://bcdn.docswell.com/page/8EDKV5WN7G.jpg)

修正は 2 箇所だけ。
plain :: Box Int
2 plain = fmap g $
3
fmap g $
4
fmap g $
5
Box [1,2]
1
6
yoneda :: Box Int
8 yoneda = lowerYoneda $
9
fmap g $
10
fmap g $
11
fmap g $
12
liftYoneda $
13
Box [1,2]
7
liftYoneda と lowerYoneda が追加されている。
18 / 67


# Page. 19

![Page Image](https://bcdn.docswell.com/page/V7PKVG9NJ8.jpg)

修正後のコードの実行結果は以下の通り。
1 ghci&gt;
yoneda
2 重い処理
3 Box [4,5]
重い処理の呼び出しが 1 回だけになった。
一方で、出力結果に変化はない。
計算結果を変えずに高速化できた！
19 / 67


# Page. 20

![Page Image](https://bcdn.docswell.com/page/2JVVZ6MYJQ.jpg)

高速化の謎を探るため、liftYoneda と lowerYoneda の実装を調べる。
liftYoneda :: Functor f =&gt; f a -&gt; Yoneda f a
2 liftYoneda a = Yoneda (\f -&gt; fmap f a)
1
3
lowerYoneda :: Yoneda f a -&gt; f a
5 lowerYoneda (Yoneda f) = f id
4
参考：https://hackage-content.haskell.org/package/kan-extensions-5.2.8/docs/src/Data.Functor.Yoneda.html
20 / 67


# Page. 21

![Page Image](https://bcdn.docswell.com/page/5EGL4NGWJL.jpg)

図で書くと…
liftYoneda
f a
Yoneda f a
lowerYoneda
f a == [Int]の場合は…
liftYoneda
[Int]
Yoneda [] Int
lowerYoneda
21 / 67


# Page. 22

![Page Image](https://bcdn.docswell.com/page/4JQYGQXQ7P.jpg)

具体例
[Int]の例として、[1,2]を考える。
liftYoneda
[1,2]
Yoneda (\f -&gt; fmap f [1,2])
fmap id [1,2]
Yoneda (\f -&gt; fmap f [1,2])
lowerYoneda
liftYoneda と lowerYoneda は互いに逆関数になっている。
22 / 67


# Page. 23

![Page Image](https://bcdn.docswell.com/page/K74W5N6YE1.jpg)

yoneda は右図の赤い経路で計算している。
liftYoneda
Box Int
yoneda :: Box Int
2 yoneda = lowerYoneda $
3
fmap g $
4
fmap g $
5
fmap g $
6
liftYoneda $
7
Box [1,2]
Yoneda Box Int
1
fmap g
Box Int
Yoneda Box Int
fmap g
高速化の理由を調べるため、Yoneda f の
fmap の定義を確認する。
Box Int
fmap g
Yoneda Box Int
fmap g
Box Int
fmap g
Yoneda Box Int
lowerYoneda
23 / 67
fmap g


# Page. 24

![Page Image](https://bcdn.docswell.com/page/LJ1YW5VNEG.jpg)

Yoneda f の fmap の定義
instance Functor (Yoneda f) where
2 fmap f m = Yoneda (\k -&gt; runYoneda m (k . f))
1
Yoneda の定義
newtype Yoneda f a
2
= Yoneda { runYoneda :: forall b. (a -&gt; b) -&gt; f b }
1
参考：https://hackage-content.haskell.org/package/kan-extensions-5.2.8/docs/src/Data.Functor.Yoneda.html
24 / 67


# Page. 25

![Page Image](https://bcdn.docswell.com/page/GJWG653M72.jpg)

具体例
g x = x + 1 として考える。
liftYoneda
[1,2]
Yoneda (\f -&gt; fmap f [1,2])
fmap g
fmap g
[2,3]
fmap (id.g) [1,2]
Yoneda (\f -&gt; fmap (f.g) [1,2])
lowerYoneda
25 / 67


# Page. 26

![Page Image](https://bcdn.docswell.com/page/4EZLYNVM73.jpg)

fmap g を繰り返す場合
liftYoneda
xs
Yoneda (\f -&gt; fmap f xs)
fmap g
fmap g
fmap g xs
Yoneda (\f -&gt; fmap (f.g) xs)
fmap g
fmap g (fmap g xs)
fmap g
fmap ((id.g).g) xs
Yoneda (\f -&gt; fmap ((f.g).g) xs)
lowerYoneda
fmap が満たすべき性質 (fmap f) . (fmap g) == fmap (f . g)
26 / 67


# Page. 27

![Page Image](https://bcdn.docswell.com/page/Y76WD8557V.jpg)

パフォーマンス改善の理由
Yoneda を経由することで、fmap g の合成が、g の合成の fmap に変
わった。 重い fmap g の処理が 1 回だけになり、パフォーマンスが
改善した。
(fmap g) . (fmap g) . (fmap g)
改善
fmap (g . g . g)
27 / 67


# Page. 28

![Page Image](https://bcdn.docswell.com/page/G75M39YG74.jpg)

注意
実際には Yoneda を用いたからといって直ちに fmap の合成のパ
フォーマンスが改善するわけではない。
GHC は fmap の合成を自動で最適化することがあるため、工夫しな
くても十分に速い場合がある。
28 / 67


# Page. 29

![Page Image](https://bcdn.docswell.com/page/9J29Z2GDER.jpg)

ここまでのまとめ
• Haskell と Kan 拡張の関係を知りたい
• Kan 拡張に関するパッケージ kan-extensions がある
• kan-extensions パッケージの使い道を知りたい
• 使い道の一つとして、Yoneda を用いた fmap の合成を最適化する例
がある
• Yoneda は fmap の合成を合成の fmap に変換することで fmap の回数
を 1 回にまとめることができる
29 / 67


# Page. 30

![Page Image](https://bcdn.docswell.com/page/DEY4RYVMJM.jpg)

Codensity
30 / 67


# Page. 31

![Page Image](https://bcdn.docswell.com/page/VJNYDPM378.jpg)

🙇
謝罪
プロポーザルでは Codensity でパフォーマンス改善する具体例を紹
介すると書いていましたが、時間が足りないことと数式を並べるよ
りも良い説明を思いつかないことから割愛いたします。
この発表では具体例ではなく概要だけを紹介します。
31 / 67


# Page. 32

![Page Image](https://bcdn.docswell.com/page/YE9PG3NPJ3.jpg)

ここまで、fmap の合成の最適化について扱った。
↓
fmap 以外はどうか？
Codensity を用いると、次のような例について同様の最適化ができ
る。
((m &gt;&gt;= k1) &gt;&gt;= k2) &gt;&gt;= k3
32 / 67


# Page. 33

![Page Image](https://bcdn.docswell.com/page/GE8DVMKXED.jpg)

Codensity は Yoneda と似たような感じで定義されている。
newtype Yoneda f a = Yoneda
2
{ runYoneda :: forall b. (a -&gt; b) -&gt; f b }
1
3
newtype Codensity m a = Codensity
5
{ runCodensity :: forall b. (a -&gt; m b) -&gt; m b }
4
参考：https://hackage-content.haskell.org/package/kan-extensions-5.2.8/docs/src/Control.Monad.Codensity.html
33 / 67


# Page. 34

![Page Image](https://bcdn.docswell.com/page/LELM53ZN7R.jpg)

fmap の合成は Yoneda を経由することで合成の fmap に変換できた。
変換
(fmap g) . (fmap f)
fmap (g . f)
(&gt;&gt;=)の合成(m &gt;&gt;= k) &gt;&gt;= h は Codensity を経由することで次の形
に変換できる。
変換
(m &gt;&gt;= k) &gt;&gt;= h
m &gt;&gt;= (\x -&gt; k x &gt;&gt;= h)
(&gt;&gt;=)が満たすべき性質(m &gt;&gt;= k) &gt;&gt;= h ≡ m &gt;&gt;= (\x -&gt; k x &gt;&gt;= h)
34 / 67


# Page. 35

![Page Image](https://bcdn.docswell.com/page/4JMY3DVQJW.jpg)

Codensity を経由することで、(&gt;&gt;=)の計算方法を変えることができ
る。 m &gt;&gt;= k の処理が重い場合、これを回避することでパフォーマ
ンスを改善することができる。
(m &gt;&gt;= k) &gt;&gt;= h
改善
m &gt;&gt;= (\x -&gt; k x &gt;&gt;= h)
35 / 67


# Page. 36

![Page Image](https://bcdn.docswell.com/page/PJR9Q42K79.jpg)

ここまでのまとめ
• Yoneda とよく似た Codensity が kan-extensions に存在する。
• fmap の合成は Yoneda で高速化できる
• (&gt;&gt;=)の合成は Codensity で高速化できる
36 / 67


# Page. 37

![Page Image](https://bcdn.docswell.com/page/PEXQ52D5JX.jpg)

Ran
37 / 67


# Page. 38

![Page Image](https://bcdn.docswell.com/page/3EK96MXRED.jpg)

Yoneda と Codensity はよく似ている。
newtype Yoneda
2
= Yoneda
1
f a
{ runYoneda
:: forall b. (a -&gt;
b) -&gt; f b }
3
newtype Codensity m a
5
= Codensity { runCodensity :: forall b. (a -&gt; m b) -&gt; m b }
4
38 / 67


# Page. 39

![Page Image](https://bcdn.docswell.com/page/L73W6Y5G75.jpg)

R を次のように定義すると、この 2 つを一般化できそう。
newtype Yoneda
2
= Yoneda
1
f a
{ runYoneda
:: forall b. (a -&gt;
b) -&gt; f b }
3
newtype Codensity
m a
5
= Codensity { runCodensity :: forall b. (a -&gt; m b) -&gt; m b }
4
6
newtype R
8
= R
7
g h a
{ run
:: forall b. (a -&gt; g b) -&gt; h b }
39 / 67


# Page. 40

![Page Image](https://bcdn.docswell.com/page/87DKV5DNJG.jpg)

実はこの R こそが、kan-extensions で定義されている右 Kan 拡張
Ran g h a。
newtype Ran g h a
2
= Ran { runRan :: forall b. (a -&gt; g b) -&gt; h b }
1
Yoneda f a ≅ Ran Identity f a
Codensity g a ≅ Ran g g a
Ran は Yoneda と Codensity の一般化になっている。
40 / 67


# Page. 41

![Page Image](https://bcdn.docswell.com/page/VJPKVGXNE8.jpg)

あとは、Ran が圏論の右 Kan 拡張に対応していることを確認すれば
よい。
次の順番で確認する。
• Ran g h a を圏論的に表すとHom (Hom (𝑎, 𝐺 −), 𝐻)
• 右 Kan 拡張の随伴より、上記がHom(Hom(𝑎, −), Ran𝐺 𝐻)と同型
• 米田の補題より、上記がRan𝐺 𝐻(𝑎)と同型
41 / 67


# Page. 42

![Page Image](https://bcdn.docswell.com/page/2EVVZ6LYEQ.jpg)

Haskell と圏論の関係を見るために、Haskell の型、関数などを圏論
の言葉で書き直す。
• 型 a は対象 𝑎
• 関数 a -&gt; b は Hom (𝑎, 𝑏) の元。
• f a は 関手 𝐹 で 𝑎を移したもの 𝐹 (𝑎) に対応する。
• forall a. f a -&gt; g a は自然変換 Hom (𝐹 , 𝐺) に対応する。
※厳密には違うと思うが、一旦これで進める。
42 / 67


# Page. 43

![Page Image](https://bcdn.docswell.com/page/57GL4NXWEL.jpg)

Haskell の右 Kan 拡張の定義は以下のとおり。
newtype Ran g h a
2
= Ran { runRan :: forall b. (a -&gt; g b) -&gt; h b }
1
これを圏の言葉に書き換えると、次のようになる。
Hom (Hom (𝑎, 𝐺 −), 𝐻)
43 / 67


# Page. 44

![Page Image](https://bcdn.docswell.com/page/4EQYGQ8QJP.jpg)

• Ran g h a を圏論的に表すとHom (Hom (𝑎, 𝐺 −), 𝐻) ←OK
• 右 Kan 拡張の随伴より、上記がHom(Hom(𝑎, −), Ran𝐺 𝐻)と同型
• 米田の補題より、上記がRan𝐺 𝐻(𝑎)と同型
44 / 67


# Page. 45

![Page Image](https://bcdn.docswell.com/page/KJ4W5N2Y71.jpg)

圏論における右 Kan 拡張の定義
𝐶, 𝐷, 𝐸を圏として、𝐺 : 𝐶 → 𝐷, 𝐻 : 𝐶 → 𝐸を関手とする。
𝐷
𝐺
𝐶
𝐻
45 / 67
𝐸


# Page. 46

![Page Image](https://bcdn.docswell.com/page/LE1YW5MN7G.jpg)

次の 2 つの条件を満たす(Ran𝐺 𝐻, 𝜀)を𝐺に沿った𝐻の右 Kan 拡張
と呼ぶ。
1. Ran𝐺 𝐻は関手𝐷 → 𝐸で、𝜀は自然変換Ran𝐺 𝐻 ∘ 𝐺 ⇒ 𝐻
46 / 67


# Page. 47

![Page Image](https://bcdn.docswell.com/page/GEWG65DMJ2.jpg)

2. 関手𝑆 : 𝐷 → 𝐸と、自然変換𝜃 : 𝑆 ∘ 𝐺 ⇒ 𝐻に対して、次を満たす
自然変換𝜏 : 𝑆 ⇒ Ran𝐺 𝐻が一意に存在する。
𝜃 = 𝜀 ∘ 𝜏𝐺
47 / 67


# Page. 48

![Page Image](https://bcdn.docswell.com/page/47ZLYNGMJ3.jpg)

𝐻をRan𝐺 𝐻に送る関手をRan𝐺 で表す。
関手𝐶 → 𝐸からなる圏を𝐸 𝐶 のように書くと、Ran𝐺 は関手𝐸 𝐶 →
𝐸𝐷。
𝐷
Ran𝐺 𝐻
𝐺
𝐶
𝐻
𝐸𝐶
𝐸
48 / 67
Ran𝐺
𝐸𝐷


# Page. 49

![Page Image](https://bcdn.docswell.com/page/YJ6WD8Y5JV.jpg)

関手Ran𝐺 : 𝐸 𝐶 → 𝐸 𝐷 には随伴関手（良い性質を持つ逆向きの関手）
がある。 𝐺−1 : 𝐸 𝐷 → 𝐸 𝐶 を𝑆 ↦ 𝑆 ∘ 𝐺とすると、𝐺−1 はRan𝐺 の左随
伴になる。
49 / 67


# Page. 50

![Page Image](https://bcdn.docswell.com/page/GJ5M39GGJ4.jpg)

議論しやすいように、Haskell の圏 Hask の代わりに 集合の圏 Set
で考える。
𝐸をSetに置き換える。
𝐷
Ran𝐺 𝐻
𝐺
𝐺−1
𝐶
𝐻
Set𝐶
Set
Set𝐷
Ran𝐺
50 / 67


# Page. 51

![Page Image](https://bcdn.docswell.com/page/9E29Z2YD7R.jpg)

随伴と𝐺−1 ⊣ Ran𝐺 と、随伴の定義より任意の𝑆 ∈ 𝐸 𝐷 と𝐻 ∈ 𝐸 𝐶 に
対して、以下が成り立つ。
HomSet𝐶 (𝐺−1 𝑆, 𝐻) ≅ HomSet𝐷 (𝑆, Ran𝐺 𝐻)
𝑆は任意なので、𝑆 = Hom𝐷 (𝑎, −) でも成り立つ。
HomSet𝐶 (𝐺−1 Hom𝐷 (𝑎, −), 𝐻) ≅ HomSet𝐷 (Hom𝐷 (𝑎, −), Ran𝐺 𝐻)
※任意の𝑏 ∈ 𝐷に対して、Hom𝐷 (𝑎, 𝑏)は集合であると仮定する。つまり、𝐷は局所小圏とす
る。
51 / 67


# Page. 52

![Page Image](https://bcdn.docswell.com/page/D7Y4RYGMEM.jpg)

𝐺−1 : 𝐸 𝐷 → 𝐸 𝐶 は𝑆 ↦ 𝑆 ∘ 𝐺なので、次のように書き換えられる。
HomSet𝐶 (𝐺−1 Hom𝐷 (𝑎, −), 𝐻) = HomSet𝐶 (Hom𝐷 (𝑎, 𝐺 −), 𝐻)
まとめると
HomSet𝐶 (Hom𝐷 (𝑎, 𝐺 −), 𝐻)
= HomSet𝐶 (𝐺−1 Hom𝐷 (𝑎, −), 𝐻) （𝐺−1 に書き換え）
≅ HomSet𝐷 (Hom𝐷 (𝑎, −), Ran𝐺 𝐻)
52 / 67
(𝐺−1 ⊣ Ran𝐺 )


# Page. 53

![Page Image](https://bcdn.docswell.com/page/VENYDPG3J8.jpg)

• Ran g h a を圏論的に表すとHom (Hom (𝑎, 𝐺 −), 𝐻) ←OK
• 右 Kan 拡張の随伴より、上記がHom(Hom(𝑎, −), Ran𝐺 𝐻)と同型 ←OK
• 米田の補題より、上記がRan𝐺 𝐻(𝑎)と同型
53 / 67


# Page. 54

![Page Image](https://bcdn.docswell.com/page/Y79PG3WPE3.jpg)

示すべきこと
HomSet𝐷 (Hom𝐷 (𝑎, −), Ran𝐺 𝐻) ≅ Ran𝐺 𝐻(𝑎)
これは米田の補題より成り立つ。
米田の補題
𝐷を局所小圏、𝐹 : 𝐷 → Setを関手とする。このとき次が成り立つ。
HomSet𝐷 (Hom𝐷 (𝑎, −), 𝐹 ) ≅ 𝐹 (𝑎)
54 / 67


# Page. 55

![Page Image](https://bcdn.docswell.com/page/G78DVMNX7D.jpg)

Yoneda と米田の補題の関係
Yoneda f a = Yoneda { runYoneda :: forall b. (a -&gt; b) -&gt; f b }
liftYoneda
f a
Yoneda f a
lowerYoneda
𝐹 (𝑎)
HomSet𝐷 (Hom𝐷 (𝑎, −), 𝐹 )
55 / 67


# Page. 56

![Page Image](https://bcdn.docswell.com/page/L7LM53PNJR.jpg)

• Ran g h a を圏論的に表すとHom (Hom (𝑎, 𝐺 −), 𝐻) ←OK
• 右 Kan 拡張の随伴より、上記がHom(Hom(𝑎, −), Ran𝐺 𝐻)と同型 ←OK
• 米田の補題より、上記がRan𝐺 𝐻(𝑎)と同型 ←OK
56 / 67


# Page. 57

![Page Image](https://bcdn.docswell.com/page/4EMY3D4QEW.jpg)

まとめ
集合の圏Setを Haskell の圏だと思うと、Ran g h a と右 Kan 拡張
Ran𝐺 𝐻(𝑎)が同型であることを確認できる。
HomSet𝐶 (Hom𝐷 (𝑎, 𝐺 −), 𝐻)
（Haskell の右 Kan 拡張）
≅ HomSet𝐷 (Hom𝐷 (𝑎, −), Ran𝐺 𝐻)
(𝐺−1 ⊣ Ran𝐺 )
≅ Ran𝐺 𝐻(𝑎)
（米田の補題）
57 / 67


# Page. 58

![Page Image](https://bcdn.docswell.com/page/PER9Q4WKJ9.jpg)

まとめ
58 / 67


# Page. 59

![Page Image](https://bcdn.docswell.com/page/P7XQ52P5EX.jpg)

最初の問い
Haskell の概念も Kan 拡張として理解できるのでは？
Haskell
?
影響
圏論
すべての概念
59 / 67
Kan 拡張


# Page. 60

![Page Image](https://bcdn.docswell.com/page/37K96MDR7D.jpg)

パフォーマンス改善に利用できる Yoneda や Codensity が Kan 拡張
の例となっている。
Haskell
影響
圏論
Yoneda、Codensity など
すべての概念
60 / 67
Kan 拡張


# Page. 61

![Page Image](https://bcdn.docswell.com/page/LJ3W6YRGJ5.jpg)

まとめ
• Yoneda は fmap の合成のパフォーマンスを改善できる
• Codensity は(&gt;&gt;=)の合成のパフォーマンスを改善できる
• Ran は Yoneda と Codensity の一般化である
• Ran と右 Kan 拡張の対応は、右 Kan 拡張の随伴と米田の補題を用
いて示せる
ご清聴ありがとうございました。
61 / 67


# Page. 62

![Page Image](https://bcdn.docswell.com/page/8JDKV5YNEG.jpg)

余談
Haskell
影響
圏論
すべての概念
この状況は Kan 拡張チャンス!!である。
62 / 67
Kan 拡張


# Page. 63

![Page Image](https://bcdn.docswell.com/page/VEPKVG6N78.jpg)

Haskell
影響
圏論
Ran影響 すべての概念
すべての概念
Kan 拡張
「実はこの発表内容自体が Kan 拡張になっていたのだ」と言えると
面白かったが、これは過言。
63 / 67


# Page. 64

![Page Image](https://bcdn.docswell.com/page/27VVZ63Y7Q.jpg)

すべての概念は Kan 拡張
Kan 拡張の例
• 関手𝐹 : 𝐶 → 𝐷が右随伴を持つとき、その右随伴はLan𝐹 id𝐶
• 関手𝐺 : 𝐷 → 𝐶が左随伴を持つとき、その左随伴はRan𝐺 id𝐷
• 極限は右 Kan 拡張
• 余極限は左 Kan 拡張
随伴も極限も抽象的な概念。
64 / 67


# Page. 65

![Page Image](https://bcdn.docswell.com/page/5JGL4N3W7L.jpg)

随伴の例
極限の例
• 自由群関手は忘却関手の左随
伴
• 集合𝐴に対して− × 𝐴は(−)𝐴 の
左随伴
• 終対象
• 直積
• 等化子
• 引き戻し
• 逆極限
65 / 67


# Page. 66

![Page Image](https://bcdn.docswell.com/page/47QYGQ5QEP.jpg)

終対象の例
直積の例
逆極限の例
• 一元集合
• 自明群（始対象で
もある）
• 整数の整除関係の
圏における 0
• Unit 型 ()
• 集合の直積
• 位相空間の直積
• 整数の整除関係の
圏における最大公
約数
• タプル (a,b)
• 𝑝-進整数
• 副有限群
66 / 67


# Page. 67

![Page Image](https://bcdn.docswell.com/page/KE4W5N9YJ1.jpg)

参考文献
[1] alg-d. Kan 拡張. https://alg-d.com/math/kan_extension/kan_extension.pdf.
[2] Bartosz Milewski. Kan Extensions | Bartosz Milewski’s Programming Cafe. https://
bartoszmilewski.com/2017/04/17/kan-extensions/.
[3] Edward A. Kmett. Kan-extensions. https://hackage.haskell.org/package/kanextensions.
[4] Saunders Mac lane and Saunders Maclane. Categories for the working
mathematician, Vol. 5. Springer, 1971.
[5] Tom Leinster. ベーシック圏論, 丸善出版, 2017.
67 / 67


