Bob*_*Bob 14 io monads haskell functional-programming comonad
输出是有效的计算.因此将它封装成monad是有意义的.但是输入是上下文敏感的计算.因此将它封装到comonad中会更有意义.
但是在Haskell中,输入和输出都封装在IO
monad中.为什么?
Dav*_*vid 18
comonad有一个extract :: w a -> a
方法,不能(合理地)实现IO
.
在comonad意义上,输入不是真正的上下文敏感.comonad的"上下文敏感性"意味着它对数据结构中较大的上下文敏感.例如,列表拉链就像一个列表,在任何给定时刻列表中都有一些关于"我们在哪里"的额外位置信息.IO
数据结构实际上没有任何实际结构,因此没有任何上下文对它敏感.
该Monad
结构允许我们IO
使用>>=
操作从类型内部访问输入,因此可以正常工作.
另外,请注意术语"有效"和"上下文敏感"是非正式的,因此,对于monad和comonad的所有示例可能并不完全有意义:函数monad是否真的"有效"?是(,) e
comonad真的"上下文敏感"?
顺便说一下,开发关于monad和comonad如何工作的直觉的最好方法是通过使用它们获得经验(这也适用于许多其他事情).不幸的是,没有一种很好的方法可以用一种简短的短语来概括它,例如"有效"或"上下文敏感",这种方式可以让你了解它们的实际工作方式.这些短语可以帮助一些,但重要的是要记住它们的局限性.
此外,理解类型类的最佳方法是了解其实例(尝试遍历所有提供的实例并将其弄清楚).完成后,您可以查看类型类如何连接到所有类型.这将为您提供类型类"含义"的良好直觉.我还应该指出,在经历其实例时,最好在脑子(至少)中保留可能为类型类提供的任何法律.
comonad的签名extract :: w a -> a
意味着我们可以a
用纯计算进行计算,没有任何副作用.
另一方面,IO
当我们想要使用副作用产生一些价值时,我们使用.即使是看似仅输入的东西也会产生副作用.例如:通过网络接收数据,从文件读取字节并提升流位置,从数据库读取数据可能会产生副作用,例如打开网络连接,记录访问,激活某些触发器等等.所以comonad不是适当的抽象IO
.