函数的副作用

时间:2022-09-06 19:25:35

转载时请注明出处和作者联系方式

作者联系方式:会飞的鱼 <parker30_liu at hotmail dot com>


      纯函数是没有副作用的,一般是表达式计算,有副作用的monad在求值前也是没有副作用的,可以看成是表达式的组合。当这些没有副作用的表达式计算和组合与现实世界发生联系时,就出现有副作用的不纯的函数了。
      在haskell里,没有副作用的纯函数和有副作用的不纯的函数是显式严格分开的,没有办法将有副作用的不纯函数隐含到纯函数中。唯一的方式就是通过有副作用的monad来联系纯和不纯的两个世界。当我们对这个有副作用的monad求值时,副作用就出现了。比如IO monad,main函数本身是没有副作用的,当我们开始运行runIO时,副作用就出现并生效了,putStrLn等IO函数才开始向终端输出字符串。runIO则是由haskell的运行时环境引发的。
      纯函数和不纯的函数可以大致类比为组合电路和时序电路。纯函数和组合电路是没有状态的,不纯的函数和时序电路是有状态的。
      组合电路的计算依赖是门电路的依赖,纯函数的计算依赖是表达式依赖。组合电路的计算速度是非常快的,只与参与计算的门电路的延迟有关,都是并行的,和时钟没有关系。纯函数天生适合并行计算,其计算速度和硬件电路的并行能力有关。
      时序电路的计算依赖是前一拍时钟的计算结果,不纯函数的计算依赖是前一个不纯函数的计算结果,都是串行的。时序电路的计算速度和时钟有关系,时钟越快则计算速度越快。不纯的函数的计算是串行的,因此其计算速度和硬件电路的并行能力无关。
      我们的现实世界也是有时序的,这些时序由永不停止的时间驱动着。