Что такое Comonad и чем они полезны?

16

Недавно я стер свои знания о том, как работают монады. Я также был введен в понятие «комонадой» , которая описывается как обратный двойной монады . Тем не менее, я не могу обернуть голову вокруг этого.

Чтобы понять монады, я сделал для себя аналогию:

Монады можно рассматривать как «план построения конвейерных выражений».

Чтобы определить новую Monad (новый тип конвейерно-ленточной системы), вам необходимо определить:

  1. Способ размещения чего-либо на конвейерной ленте, например, «запуск» конвейерной ленты. (Известный как unitили return)
  2. Способ соединения машины (выражения), которая будет частью конвейерной ленты, с конвейерной лентой. (Известный как joinили bindили >>=).

(Существует третья операция, которая забирает текущую конвейерную ленту, выбрасывает ее содержимое и запускает новую конвейерную ленту, известную как >>, но она используется очень редко.)

Для правильной совместной работы машин и конвейеров вам необходимо убедиться, что:

  1. Если вы положили что-то на ленточный конвейер и пропустили его через машину, выходной сигнал должен быть таким же, как при ручной передаче через машину. (Левая идентичность)
  2. Если вы хотите поместить конвейерную ленту между уже существующей конвейерной лентой, вы не должны иметь конвейерную ленту с конвейерной лентой сверху, а одну длинную конвейерную ленту. (Правильная идентичность)
  3. Для вывода не должно иметь значения, если вы вручную используете машину A, а затем пропускаете результат через BC, подключенный к конвейеру, или если вы используете AB, подключенную к конвейеру, а затем пропускаете результат вручную через C. Другими словами: ((a >> = b) >> = c) должен совпадать с (a >> = (b >> = c)) (ассоциативность)

Самая простая конвейерная лента - та, которая просто принимает входные данные и всегда переходит к следующему выражению. Вот что такое «трубопровод».

Другая возможность, это позволить ему пройти через следующую машину, если для значения выполнено какое-то условие. Это означает, что если в некоторых промежуточных выражениях значение меняется на то, что больше не разрешено, то остальные выражения будут пропущены. Это то, что делает монада «Возможно» в Хаскеле.

Вы также можете выполнять другие необычные правила копирования / изменения значений до или после их передачи на компьютер. Пример: парсеры (здесь, если выражение возвращает результат «сбой», значение перед выражением используется в качестве вывода).

Конечно, аналогия не идеальна, но я надеюсь, что она дает хорошее представление о том, как работают монады.

Однако у меня много проблем, чтобы перевернуть эту аналогию с ног на голову, чтобы понять Comonads. Из небольшого количества информации, которую я нашел в Интернете, я знаю, что Comonad определяет:

  • extractЭто своего рода обратная сторона return, то есть она берет значение из Comonad.
  • duplicate, что является своего рода обратным join, то есть он создает две Comonads из одного.

Но как создать экземпляр Comonad, если мы можем только извлечь из них или продублировать их? И как они на самом деле могут быть использованы? Я видел этот очень удивительный проект и разговоры о нем (о которых я, к сожалению, очень мало понимал), но я не уверен, какую именно часть функций обеспечивает Comonad.

Что такое Comonad? Для чего они полезны? Как их можно использовать? Они съедобны?

Qqwy
источник
2
"Как создать экземпляр Comonad, если мы можем только извлечь из них или продублировать их?" - Я отвечу на ваш вопрос вопросом: как можно использовать монаду, если вы можете только поднять значения в них и вычислить последовательности?
Бенджамин Ходжсон
1
«Машина в конце конвейерной ленты» (кроме: я не нахожу аналогий, которые могут быть полезны, когда говорят о монадах) IOмонады, это система времени исполнения Haskell, которая вызывает main. Там тоже unsafePerformIO, конечно. Если вы хотите думать о Maybeмонаде как о «машине на конце конвейерной ленты», вы можете использовать ее maybe.
Бенджамин Ходжсон
1
Но, переворачивая ваше объяснение, когда вы хотите создать комонадное значение в начале цепочки cobindприложений, должна быть какая-то функция, которая делает что-то полезное с внутренним представлением вашей комонады.
Бенджамин Ходжсон
2
конкретный экземпляр comonad или monad может явно иметь больше функциональных возможностей, чем требуется только для реализации классов типов
jk.
2
Не то чтобы это было полезно, если вы не подходите к этому вопросу с теоретико-теоретической / математической стороны, но я хотел бы отметить, что комонада не обратная, а скорее двойственная монады.
Jörg W Mittag

Ответы:

11

Комонада, как и монада, представляет собой математическую структуру в теории категорий. Со-префикс очень часто используется для обозначения «инверсий», как вы говорите (хотя я не думаю, что чистые математики согласны с выбором слова).

В теории категорий существуют categories, которые кратко objectsобозначают совокупность (любого типа или природы, внутренняя структура не имеет значения) и некоторые arrowsмежду этими объектами. Чтобы что-то было категорией, стрелки должны следовать некоторым законам (левая / правая идентичность и ассоциативность), но это не очень важно здесь.

Теперь теория категорий очень абстрактна / трудна для понимания и обширна. Требуется много времени, чтобы пройти все это (и я не изучал это формально, я только знаю некоторые основы), но есть понятие, которое называется a dual. В принципе, для каждой категории вы можете создать opposite category, просто выполнив одно и то же, но «перевернув все стрелки». Это очень наивное определение, но трудно попытаться подвести итог. Двойственное что-то в категории C - это то же самое в противоположной категории C_op (головная боль еще есть?)

В любом случае, если у вас есть монада над какой-то категорией (а категория может быть, например, категорией, в которой объекты являются типами в каком-то языке программирования, а стрелки - это функции между типами), то комонада - это в основном то же самое, только вы перевернули все стрелки (в данном случае это похоже на изменение сигнатур функций).

Более «практическое» описание (хотя и не СУПЕР-практическое) можно найти в этой дискуссии между Эриком Мейером и Брайаном Бекманом, где они обсуждают понятие дуальности и как Эрик делал «реверсирование стрелок» IEnumerable<T>в C #, когда создание реактивной структуры и IObservable<T>(что, насколько я могу судить, и я рад, что меня исправили, в основном это экземпляр списка comonad).

Другой практический пример комонад, упомянутых в видео, - это Task<T>тип в .NET, где Task<U> ContinueWith<U>(Func<Task<T>, U>)будет двойной тип bind(или SelectManyкак он называется в C #)

Сара
источник