Почему IO - это монада, а не комонада?
Выход является эффективным вычислением. Таким образом, имеет смысл заключить его в монаду. Но вход является контекстно-зависимым вычислением. Таким образом, было бы больше смысла заключать его в комонаду.
Однако в Haskell оба входа и выхода инкапсулированы в IO
монада. Зачем?
2 ответа
Комонада имеет extract :: w a -> a
метод, который не может (разумно) быть реализован для IO
,
Ввод не является действительно контекстно-зависимым в смысле comonad. "Чувствительность к контексту" для comonad означает, что он чувствителен к большему контексту в структуре данных. Например, застежка-молния списка подобна списку с некоторой дополнительной информацией о положении "где мы находимся" в списке в любой данный момент. Там на самом деле нет никакой реальной структуры IO
структура данных, поэтому нет контекста, к которому она может быть чувствительной.
Monad
структура позволяет нам получить доступ к входу изнутри IO
введите с помощью >>=
операция, так что все работает хорошо.
Также обратите внимание, что термины "эффективный" и "контекстно-зависимый" являются неформальными и, как следствие, могут не иметь полного смысла для всех примеров монад и комонад: действительно ли функция-монада "эффективна"? Это (,) e
comonad действительно "контекстно-зависимый"?
Кстати, лучший способ развить интуицию о том, как работают монады и комонады, - это получить опыт их использования (это касается и многих других вещей). К сожалению, на самом деле не существует хорошего способа суммировать их с помощью короткой фразы типа "эффективный" или "контекстно-зависимый" таким образом, чтобы дать вам представление о том, как они на самом деле работают. Эти фразы могут помочь некоторым, но важно помнить об их ограничениях.
Кроме того, лучший способ понять класс типов - это понять его экземпляры (попробуйте просмотреть все предоставленные экземпляры и выяснить их). Сделав это, вы можете посмотреть, как класс типов соединяется со всеми из них. Это даст вам хорошее представление о том, что "тип" означает "класс". Я должен также отметить, что это хорошая идея - держать любые законы, которые могут быть предоставлены для класса типов, в глубине вашего сознания (по крайней мере), проходя через его экземпляры.
Подпись комонады extract :: w a -> a
означает, что мы можем вычислить a
с чистым вычислением, без каких-либо побочных эффектов.
С другой стороны, мы используем IO
когда мы хотим произвести некоторую ценность, используя побочные эффекты. Даже вещи, которые кажутся только входными, имеют побочные эффекты. Например: получать данные по сети, читать байты из файла и улучшать позицию потока, чтение данных из базы данных может иметь побочные эффекты, такие как открытие сетевого подключения, регистрация доступа, активация некоторых триггеров и т. Д. Так что Comonad не правильная абстракция для IO
,