这是一篇关于 Haskell 语言中副作用(side effects)和函数式编程的文章,主要内容如下:
- 副作用作为一等值(Side effects as first class values):Haskell 中的有副作用计算是一等值,可以存储在变量或数据结构中供以后使用。例如
randomRIO函数,创建包含randomRIO调用的列表时不会生成随机数,只有在do块中调用时才会执行。do块不是魔法,可转换为*>(序列右)和>>=(绑定)两个运算符,*>用于组合两个副作用,>>=用于将左边副作用的结果用于影响右边的函数调用。 - 揭开
do块的神秘面纱(De-mystifying do blocks):do块可转换为*>和>>=运算符,*>用于组合副作用,>>=用于将左边副作用的结果用于影响右边的函数调用。 操作副作用的函数(Functions that operate on side effects):
pure:用于构造总是产生特定值的副作用对象。fmap:用于对副作用对象的结果进行转换,其别名是<$>。liftA2等:用于基于多个副作用创建产生新值的副作用对象。
- 深入研究副作用的一等性(Leaning into the first classiness of effects):通过
traverse和for等函数,可以更高效地处理副作用和集合,还可以使用State类型来管理可变状态,使代码更简洁和高效。 - 不需要关心的事情(Things you never need to care about):一些历史函数有更现代的等价物,如
>>等价于*>,return等价于pure等。 - 附录 A:避免成功和无用性(Appendix A: Avoiding success and uselessness):Haskell 社区避免为了成功而牺牲其价值观,Haskell 从拒绝任意副作用开始,后来找到了一种允许代码描述副作用而不实际执行它们的方法,从而获得了实用性。
- 附录 B:为什么
fmap对副作用和列表都起作用(Appendix B: Why fmap maps over both side effects and lists):fmap的最通用类型签名是fmap :: Functor f => (a -> b) -> f a -> f b,列表、副作用对象和可空值都是函子,都支持fmap操作。 - 附录 C:可折叠和可遍历(Appendix C: Foldable and Traversable):
sequenceA、traverse等函数的结果保留变体保证创建的副作用数据结构与传入的原始数据结构具有相同的形状,但对于某些数据结构,这是一个更严格的要求,sequenceA_、traverse_等可以处理更多的集合类型。
总的来说,Haskell 语言通过将副作用作为一等值,并提供了一系列用于处理副作用的函数和类型,使得在函数式编程中可以更灵活、高效地处理有副作用的代码,同时保持代码的可读性和可维护性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。