3

Parsec多数の小さなファイルに対してパーサーを実行しようとしていますが、開いているファイルが多すぎるというエラーが表示されます。厳密な IO を使用する必要があることは理解していますが、その方法がわかりません。これは問題のあるコードです:

files = getDirectoryContents historyFolder

hands :: IO [Either ParseError [Hand]]
hands = join $ sequence <$> parseFromFile (many hand) <<$>> files

注:私の<<$>>機能はこれです:

(<<$>>) :: (Functor f1, Functor f2) => (a -> b) -> f1 (f2 a) -> f1 (f2 b)
a <<$>> b = (a <$>) <$> b
4

2 に答える 2

5

あなたの関数が現在どのように見えるかはわかりませんがparseFromFile(おそらくそれを質問に含めることをお勧めします)、Prelude.readFile@ Markus1189が指摘しているように、遅延I / Oが含まれているを使用していると思います。厳密な I/O を取得するには、 Data.Text.IO.readFilereadFileなどの strict が必要です。

ストリーミング データ ライブラリを使用すると、ファイル全体を一度にメモリに読み込むことを回避できpipesますconduitが、私の知る限り、parsec はこれを可能にするストリーミング インターフェイスを提供していません。一方、attoparsec にはそのようなストリーミング インターフェイスが含まれており、パイプとコンジットの両方に attoparsec アダプター ライブラリ (たとえば、Data.Conduit.Attoparsec ) があります。

tl;dr: おそらく次のヘルパー関数が必要です:

import qualified Data.Text as T
import qualified Data.Text.IO as TIO

readFileStrict :: FilePath -> IO String
readFileStrict = fmap T.unpack . TIO.readFile
于 2014-04-06T12:52:23.340 に答える