对不起,还有另一个FP +副作用问题,但是我找不到一个可以完全回答我的问题。
我对函数式编程的(有限的)理解是,应将状态/副作用最小化并与无状态逻辑分开。
我还收集了Haskell的方法,即IO monad,它通过将有状态的动作包装在一个容器中以供以后执行(被认为超出程序本身的范围)来实现。
我试图理解这种模式,但实际上是确定是否在Python项目中使用它,因此要避免使用Haskell规范。
粗暴的例子来了。
如果我的程序将XML文件转换为JSON文件:
def main():
xml_data = read_file('input.xml') # impure
json_data = convert(xml_data) # pure
write_file('output.json', json_data) # impure
IO monad的方法不是有效地做到这一点:
steps = list(
read_file,
convert,
write_file,
)
然后通过不实际调用这些步骤来放任自己的责任,而是让口译员这样做?
换一种说法,就像写:
def main(): # pure
def inner(): # impure
xml_data = read_file('input.xml')
json_data = convert(xml_data)
write_file('output.json', json_data)
return inner
然后期待别人打来电话inner()
,说您的工作已经完成,因为它main()
很纯正。
基本上,整个程序最终将包含在IO monad中。
实际执行代码时,读取文件后的所有内容都取决于该文件的状态,因此仍然会遭受与命令式实现相同的与状态相关的错误,因此,作为一名程序员,您将真正维护任何东西吗?
我完全赞赏减少和隔离有状态行为的好处,这实际上就是为什么我这样构造命令式版本的原因:收集输入,做纯净的东西,吐出输出。希望它convert()
可以是完全纯净的,并可以从可缓存性,线程安全性等方面受益。
我也很欣赏monadic类型很有用,特别是在以可比较类型运行的管道中,但看不到为什么IO应该使用monad,除非已经在这样的管道中使用了。
处理IO monad模式带来的副作用(我所缺少的)还有其他好处吗?
main
Haskell程序中的类型为IO ()
IO操作。这实际上根本不是一个函数;这是一个价值。您的整个程序是一个纯值,其中包含告诉语言运行时应该执行的操作的指令。所有不纯净的东西(实际上是执行IO操作)不在程序的范围之内。
read_file
)并将其用作下一个计算的参数(write_file
)。如果您只有一系列独立的动作,则不需要Monad。