Haskell:一次保存一个listitem来存档

时间:2013-08-01 10:21:35

标签: haskell

我想将一个巨大的列表A保存到文本文件中。 writeFile似乎只在A的calc化结束时保存列表,崩溃因为我的内存不足以存储整个列表。

我已尝试使用

writeFile "test.txt" $ show mylistA

现在我尝试保存列表中的元素,因为它们是使用以下方法计算的:

[appendFile "test2.txt" (show x)|x<-mylistA]

但它不起作用,因为:

  

使用`print'没有(Show(IO()))的实例可能的修复:为(Show(IO())添加实例声明)在交互式GHCi命令的stmt中:打印它< / p>

你能帮我解决这个问题,还是给我一个解决方案,将我的巨大列表A保存到文本文件中?

谢谢

3 个答案:

答案 0 :(得分:4)

问题是您的列表具有类型[ IO () ]或“IO操作列表”。由于IO位于out类型的“内部”,我们无法在IO monad中执行此操作。我们想要的是IO ()。所以列表理解不会在这里破解它。

我们可以使用一个函数来转换[IO ()] -> IO [()],但这种情况适合于更简洁的组合器。

相反,我们可以使用名为mapM_的简单预定义组合子。在Haskell前奏中,M表示它是monadic,而_表示它在我们的案例m ()中返回IO ()。在这种情况下使用它是微不足道的

[appendFile "test2.txt" (show x)|x<-mylistA]

变为

mapM_ (\x -> appendFile "test2.txt" (show x)) myListA

mapM_ (appendFile "test2.txt" . show) myListA

这将展现为

之类的东西
appendFile "test2.txt" (show firstItem) >>
appendFile "test2.txt" (show secondItem) >>
...

所以我们永远不会把整个清单都记在内存中。

答案 1 :(得分:2)

您可以使用sequence中的Control.Monad函数来获取(懒惰生成的)IO操作列表并一次执行一个

>>> import Control.Monad

现在你可以做到

>>> let myList = [1, 2, 3]
>>> sequence [print x | x <- myList]
1
2
3
[(),(),()]

请注意,您会在结尾处获得所有返回值的列表。如果您要放弃返回值,只需使用sequence_代替sequence

>>> sequence_ [print x | x <- myList]
1
2
3

答案 2 :(得分:0)

我只是想通过提及forM_ mapM_的翻转版本来扩展jozefg的答案。使用forM_可以得到类似于foreach循环的内容:

-- Read this as "for each `x` in `myListA`, do X"
forM_ myListA $ \x -> do
    appendFile "test2.txt" (show x)