IO相关任务的功能方式

时间:2014-01-12 20:32:37

标签: haskell functional-programming

大多数初学者都以强制方式编写与IO相关的任务。是否有任何一般性建议可帮助初学者在实施IO相关任务时切换到更实用的方式?

作为一个具体的例子,考虑沿途的目录遍历和文件处理的任务。对我来说,必要的方法是遍历目录树并按照C风格语言处理每个文件。然后我发现了Conduit库,对我来说代表了功能方式:构建源列表然后使用列表。

那么我可以说“管道方式”是IO相关任务中编程的首选功能方式吗?

2 个答案:

答案 0 :(得分:2)

管道方法不是立即建立整个列表并使用它;管道(和管道,这个问题的另一个当前流行的解决方案)的关键点是你一次只消耗一个元素。它类似于懒惰的IO,除了更原则的方式,因为懒惰的IO真的很烦人的理由并且变得正确。

第一步是尝试将尽可能多的逻辑拉入纯函数中;而不是编写parseFile :: FileName -> Result,写一个parseContents :: String -> Result并使用readFile(好吧,你也应该使用Text或ByteString而不是String,但这不相关)。

对于您的特定情况,您有三个问题:枚举要读取的文件,读取它们,然后处理内容。因此,如果您想使用conduit,您可以做的一件事就是编写一个生成文件名的Source IO FilePath,一个Conduit FilePath IO Text来获取文件名并输出其内容,以及一个{ {1}}获取内容并对其执行任何操作。然后,您可以使用Sink Text Result或类似内容将它们连接在一起,然后获得(source $= conduit) $$ sink

我认为这与反应式编程有关,btu我对反应式编程知之甚少,所以我不能说太多。

答案 1 :(得分:1)

明显的答案:对于IO任务,你应该使用IO monad。但我个人并不认为IO monad和命令式代码之间存在很大差异。这是因为IO monad包含可变状态(操作系统)并将其从一个语句传递到另一个语句。虽然IO monad不会为您的代码带来可变变量,但它允许您隐式更改某些可变状态。

最近我遇到了处理输入的有趣方法,称为反应式编程。我使用Scala绑定使用RxJava并使其有希望。主要思想是将纯事件处理程序编写到不同类型的事件中。但是杀手级的特征是事件源可以以不同的方式组合以创建封装某些逻辑的新事件源。您可以阅读有趣的文章Your Mouse is a Database,以了解更多有关此方法的动机。我不确定它会帮助你探索文件系统,但肯定会有助于编写交互式程序。