我想将一个巨大的列表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保存到文本文件中?
谢谢
答案 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)