Итак, если у нас имеются две категории,
C и
D, и два функтора,
F:
C →
D и
G:
D →
C, мы говорим, что эти два функтора образуют сопряженную пару,
F ⊣ G
если имеется взаимно-однозначное соответствие
Для сопряженной пары мы вывели два естественных преобразования,
η: Id
C → F;G
и
ε: G;F → Id
D.
Оказывается, если есть такие два естественных преобразования, для пары функторов, то они сопряжены.
Ну и правда, если есть
f: F(X) → Y
, то приложим к нему
G
, получим
G(f): G(F(X)) → G(Y)
, и соединим это с
ηX: X → G(F(X))
, получим ту самую
X → G(Y)
.
То же самое, по симметрии, проделывается и в другую сторону. Вообще, у меня тут половина рассуждений лишняя, потому что зеркальная симметрия ж (никаких бозонов).
Наши
ηX
и
εY
обладают чудесными свойствами:
Эти два чудесные свойства получаются в результате применения тех самых соответствий
α
и
β
, что были нарисованы в первой серии - попробуйте сами.
У нас есть теперь всё для монады и комонады.
Монада делается путём композиции,
T = F;G
; это функтор
T:
C →
C. В качестве монадной единицы годится уже появлявшаяся у нас
η
, а в качестве монадного умножения (a.k.a.
flatten
) возьмём
μX = G(εF(X)): G(F(G(F(X)))) → G(F(X))
.
Единица оказывается единицей относительно монадного умножения, и умножение оказывается ассоциативно - всё это следует из описанных выше свойств сопряженных функторов.
Симметрично мы можем определить комонаду, путём композиции
U = G;F
.
Пример.Возьмём категории
C=
Set и
D=
Set×Set - множества и пары множеств, и два функтора,
Δ(X) = (X,X)
и
Π((X,Y)) = X×Y
.
Первый функтор - диагональ, он множеству сопоставляет пару, состоящую из двух экземпляров оного, а второй паре множеств сопоставляет декартово произведение.
Эти два функтора сопряжены,
Δ ⊣Π
.
А именно, если есть
(f1,f2): (X,X) → (Y1, Y2)
, то это задаёт отображение
X →Y1×Y2
, и наоборот, отображение в декартово произведение
Y1×Y2
задаёт пару отображений, по компонентам.
Какая ж тут у нас монада? Монада берёт множество
X
и сопоставляет ему
X×X
. Монадная единица - диагональ (
η(x) = (x,x)
), а монадное умножение,
X×X×X×X → X×X
строится, согласно картинкам из начала этой части, из
ε: (Y1×Y2, Y1×Y2) →(Y1,Y2)
- проектированием по первой и последней координатам.
μ(x1,x2,x3,x4) = (x1,x4)
.
Кто любит симплициальные категории, увидит тут различные краюшки и рёбрушки, но это ладно, это мы лучше не будем трогать.
"Практический смысл" в программировании у этой монады вот какой: есть двоичный флаг; и наши данные от него зависят - в одном случае вызов возвращает
Y1
, а в другом
Y2
. Ну и если у нас есть функция, зависящая от того же флага, то нам надо как-то комбинировать и сплющивать; это же Reader Monad, сведённая к двоичному флагу. Ну вот эта монада и есть.
Вопросы?
(Завтра продолжу, хочу показать, как из монады можно построить сопряженную пару, и не одну.)