2

巨大なリスト A をテキストファイルに保存したいと思います。writeFile は A の計算の最後にのみリストを保存するようですが、リスト全体を保存するにはメモリが不足しているためクラッシュします。

私はこれを使って試しました

writeFile "test.txt" $ show mylistA

以下を使用して計算されるため、リストの要素を保存しようとしました。

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

しかし、次の理由で機能しません。

`print' の使用により (Show (IO ())) のインスタンスが発生しない 可能な修正: (Show (IO ())) のインスタンス宣言を追加する 対話型 GHCi コマンドの stmt に: print it

これを修正するのを手伝ってくれますか、それとも私の巨大なリスト A をテキスト ファイルに保存する解決策を教えてくれますか?

ありがとうございました

4

3 に答える 3

4

問題は、リストにタイプ[ IO () ]または「IO アクションのリスト」があることです。IOは out 型の「内側」にあるため、これを IO モナドで実行することはできません。代わりに欲しいのは ですIO ()。したがって、リスト内包表記はここではハックしません。

関数を使用して回転させることもできます[IO ()] -> IO [()]が、この場合ははるかに簡潔なコンビネーターに適しています。

代わりに、 と呼ばれる単純な定義済みのコンビネータを使用できますmapM_。Haskell のプレリュードでは、Mそれがモナドであることを意味し、私たちのケース_ではそれが返されることを意味します。この場合、それを使用するのは簡単です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) >>
...

したがって、リスト全体がメモリにあることはありません。

于 2013-08-01T10:26:38.890 に答える
2

関数sequencefromControl.Monadを使用して、(遅延生成された) IO アクションのリストを取得し、一度に 1 つずつ実行できます。

>>> 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
于 2013-08-01T10:34:42.873 に答える
0

forM_の反転バージョンである に言及して、jozefg の回答を拡張したかっただけですmapM_。を使用forM_すると、foreach ループのようなものが得られます。

-- Read this as "for each `x` in `myListA`, do X"
forM_ myListA $ \x -> do
    appendFile "test2.txt" (show x)
于 2013-08-01T13:46:25.940 に答える