资源耗尽(打开的文件太多)

时间:2012-01-03 18:10:44

标签: haskell io lazy-evaluation

我有5000个矢量,保存在5000个文件中。我需要找到他们的总和。 DF2类型只是Vector Double的同义词,并且是Num的一个实例。所以我阅读并解析所有这些文件以列出[IO DF2]并折叠它:

getFinal :: IO DF2
getFinal = foldl1' (liftA2 (+)) $ map getDF2 [1..(sdNumber runParameters)]
    where getDF2 i = fmap parseDF2 $ readFile ("DF2/DF2_" ++ show i)

但是我收到错误:

DF2: DF2/DF2_1022: openFile: resource exhausted (Too many open files)
谷歌透露这个问题很常见:​​

然而,我没有得到懒惰IO的问题。如果它是懒惰的,那为什么它在需要之前打开文件?我不明白如何使Duncan Coutts的elegant solution适应我的情况。

1 个答案:

答案 0 :(得分:6)

并不是它在需要之前打开文件;这是因为它不会关闭它们,直到你强制整个字符串。解决这个问题的一个简单方法是在读取后立即强制整个字符串;由于Vectors是严格的,最简单的方法是在解析Vector之后强制对它进行求值:

getFinal :: IO DF2
getFinal = foldl1' (liftA2 (+)) $ map getDF2 [1..(sdNumber runParameters)]
    where getDF2 i = readFile ("DF2/DF2_" ++ show i) >>= evaluate . parseDF2

这使用Control.Exception.evaluate;您可以将evaluate视为强制其参数然后返回它。这只适用于parseDF2消耗整个字符串的情况。

更优雅的解决方案是完全摆脱懒惰的IO,并使用迭代或类似的东西。但对于这么简单的用例,这可能不值得。