简体   繁体   English

为什么IO是monad而不是comonad?

[英]Why IO is a monad instead of a comonad?

An output is an effectful computation. 输出是有效的计算。 It thus makes sense to encapsulate it into a monad. 因此将它封装成monad是有意义的。 But an input is a context-sensitive computation. 但是输入是上下文敏感的计算。 It would thus make more sense to encapsulate it into a comonad. 因此将它封装到comonad中会更有意义。

However in Haskell input and output are both encapsulated in the IO monad. 但是在Haskell中,输入和输出都封装在IO monad中。 Why? 为什么?

A comonad has an extract :: wa -> a method, which cannot be (reasonably) implemented for IO . comonad有一个extract :: wa -> a方法,不能(合理地)为IO实现。

Input is not really context sensitive in the sense of a comonad. 在comonad意义上,输入不是真正的上下文敏感。 "Context sensitivity" for a comonad means that it is sensitive to the larger context in the data structure . comonad的“上下文敏感性”意味着它对数据结构中较大的上下文敏感。 For example, a list zipper is like a list with some extra position information about "where we are" in the list at any given moment. 例如,列表拉链就像一个列表,在任何给定时刻列表中都有一些关于“我们在哪里”的额外位置信息。 There is not really any actual structure to the IO data structure, so there is no context for it to be sensitive to. IO数据结构实际上没有任何实际结构,因此没有任何上下文对它敏感。

The Monad structure allows us to access the input from inside the IO type using the >>= operation, so things works out ok. Monad结构允许我们使用>>=操作从IO类型内部访问输入,因此一切正常。

Also, note that the terms "effectful" and "context sensitive" are sort of informal and, as a result, may not completely make sense for all examples of monads and comonads: Is the function monad really "effectful"? 另外,请注意术语“有效”和“上下文敏感”是非正式的,因此,对于monad和comonads的所有示例可能并不完全有意义:函数monad是否真的“有效”? Is the (,) e comonad really "context sensitive"? (,) e comonad真的是“上下文敏感”吗?

By the way, the best way to develop intuition about how monads and comonads work is to get experience by using them (this goes for many other things as well). 顺便说一下,开发关于monad和comonad如何工作的直觉的最好方法是通过使用它们获得经验(这也适用于许多其他事情)。 Unfortunately, there is not really a good way to sum them up in with a short phrase like "effectful" or "context sensitive" in a way that would give you an idea of how they actually work. 不幸的是,没有一种很好的方法可以用一种短语来表达它们,例如“有效”或“上下文敏感”,这种方式可以让你了解它们的实际工作方式。 Those phrases can help some, but it is important to remember their limitations. 这些短语可以帮助一些,但重要的是要记住它们的局限性。

Also, the best way to understand a type class is to understand its instances (try to go through all the provided instances and figure them out). 此外,理解类型类的最佳方法是了解其实例(尝试遍历所有提供的实例并将其弄清楚)。 Once you do that, you can look at how the type class connects to all of them. 完成后,您可以查看类型类如何连接到所有类型。 This will provide you with a good intuition of what the type class "means". 这将为您提供类型类“含义”的良好直觉。 I should also point out that it is a good idea to keep any laws that might be provided for a type class in the back of your mind (at least) while going through its instances. 我还应该指出,在经历其实例时,最好在脑子(至少)中保留可能为类型类提供的任何法律。

The signature of comonad's extract :: wa -> a means that we can compute a with a pure computation, without any side effects. comonad的extract :: wa -> a的签名意味着我们可以用纯计算来计算a ,没有任何副作用。

On the other hand, we use IO when we want to produce some value using side effects. 另一方面,当我们想要使用副作用产生一些值时,我们使用IO Even things that seem to be input-only have side effects. 即使是看似仅输入的东西也会产生副作用。 For example: receive data over network, read bytes from a file and advances the stream position, reading data from a database can have side effects such as opening a network connection, logging the access, activating some triggers, etc. So comonad isn't a proper abstraction for IO . 例如:通过网络接收数据,从文件读取字节并提升流位置,从数据库读取数据可能会产生副作用,例如打开网络连接,记录访问,激活某些触发器等等。所以comonad不是适当的IO抽象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM