2011-12-22 9 views
-1

私は既に存在するファイルに書きたいHaskellプログラムを書いています。プログラムはファイルにファイルを追加する前に各文字列を生成する必要があります。したがって、最初に計算全体を行い、ファイルに追加するのではなく、プログラムが計算されるごとにプログラムを追加したいと思います。ここでこのコードでLazy Evaluationを利用するにはどうすればよいですか?

は私がしようとしたコードは次のとおりです。

-- line in my do-notation of interet 
-- filename = valid filename 
-- records = list of record data types 
appendFile fileName (map recordToString records) 

recordToString :: Record -> String 
recordToString r = club r ++ "," ++ mapName r ++ "," ++ nearestTown r ++ "," ++ terrain r ++ "," ++ mapGrade r ++ "," ++ gridRefOfSWCorner r ++ "," ++ gridRefOfNECorner r ++ "," ++ expectedCompletionDate r ++ "," ++ sizeSqKm r ++ ",\n" 

私はC. A.マッキャンが、これはすでに怠惰である必要があり、言ったように、遅延評価

+0

これはまだ怠け者ではありませんか?私は 'recordToString'呼び出しの結果を強制的に強制することはありません。 –

+3

サイドノート: 'intercalate'関数を見てください。 –

答えて

4

でこの問題を解決するに興味を持っています。ただし、appendFileは、デフォルトでブロックバッファモードでファイルを開く可能性が最も高いため、作成時に行がフラッシュされません。代わりに、データは一度に数千バイトずつファイルに書き込まれます。この問題を解決するには、ちょうどあなた自身の機能ロール:

import System.IO 

appendFileLines :: FilePath -> String -> IO() 
appendFileLines fileName text = 
    withFile fileName AppendMode $ \h -> do 
    hSetBuffering h LineBuffering 
    hPutStr h text 

を次に、あなたはappendFileLinesの代わりappendFileを使用することができ、およびファイルは、一度に1つのレコードに書き込まれます。

怠け者の結果でIO操作を実行するという点で考えていることは、「遅延IO」と呼ばれます。それは一般的に悩まされていますが、あなたがここで望む効果を達成する必要はありません。 (readFileまたはgetContentsがどのように動作しているか知っていれば、それは遅延IOです)

+0

これは、それ自体が遅延IOではありません。 'hPutStr'や' appendFile'のような出力関数は、終了するまでブロックされます。しかし、* input *が( 'getContents'や' readFile'などで)遅れて読み込まれているのは、遅延IOです。 –

+0

ある意味では、私はそれが*レイジーIOであると言います。IO操作の流れとそのシステムへの影響は評価順序によって制御されています。しかし、私はそれが標準的な遅延IOとは大きく異なっていることに同意しています。私が元々言及していたのは、その質問のわずかな誤読に基づいていました。私は私の答えを明確にしようとします。 – ehird

1

Haskellは消費者としては怠け者であり、プロデューサーとしては怠け者です。 appendFileは入力時に怠惰です。つまり、出力を生成する前にすべてのコンテンツが計算されるまで待機しません。しかし、出力全体が完了するまで、appendFileは実行フローを生成しないという点で、出力には厳密です。

appendFileがバッファリングされた出力またはライン出力を使用している場合、出力の塊を計算するまでは何も書き込むことを延期することに注意してください。バッファリングが無効になっている場合は、追加するすべての文字をシステムコールする必要がありますが、これは非常に遅いです。

関連する問題