Итак, если у нас имеются две категории,
C и
D, и два функтора,
F: C → D и
G: D → C, мы говорим, что эти два функтора образуют сопряженную пару,
F ⊣ G если имеется взаимно-однозначное соответствие
Для сопряженной пары мы вывели два естественных преобразования,
η: IdC → F;G и
ε: G;F → IdD.
Оказывается, если есть такие два естественных преобразования, для пары функторов, то они сопряжены.
Ну и правда, если есть
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, сведённая к двоичному флагу. Ну вот эта монада и есть.
Вопросы?
(Завтра продолжу, хочу показать, как из монады можно построить сопряженную пару, и не одну.)