Как воспользоваться Lazy Evaluation с этим кодом? - PullRequest
0 голосов
/ 22 декабря 2011

Я пишу программу на Haskell, в которой я хочу записать в уже существующий файл.Программа должна генерировать каждую строку перед добавлением ее в файл.Поэтому вместо того, чтобы сначала выполнять все вычисления, а затем добавлять их в файл, я бы хотел, чтобы программа добавляла каждую строку по мере ее вычисления.

Вот код, который я пытался:

-- 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"

Я заинтересован в решении этой проблемы с ленивой оценкой

Ответы [ 2 ]

4 голосов
/ 22 декабря 2011

Как сказал К.А. Макканн, это должно быть уже лениво;однако appendFile, скорее всего, по умолчанию откроет файл в режиме с буферизацией блоков, что означает, что строки не будут очищены при их создании;вместо этого данные будут записываться в файл по несколько тысяч байт за раз.Чтобы решить эту проблему, просто сверните свою собственную функцию:

import System.IO

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

Затем вы можете использовать appendFileLines вместо appendFile, и файл будет записываться в одну запись за раз.

То, о чем вы, возможно, думаете, с точки зрения выполнения операций ввода-вывода с ленивыми результатами, называется «ленивый ввод-вывод»;как правило, это осуждается, но для достижения желаемого эффекта здесь не обязательно.(Если, например, вы знаете, как работают readFile или getContents, это ленивый ввод-вывод.)

1 голос
/ 22 декабря 2011

Haskell ленив как потребитель, но не как производитель.appendFile ленив при вводе, что означает, что он не будет ждать, пока весь ваш контент будет рассчитан, прежде чем производить какие-либо выходные данные.Тем не менее, он является «строгим» при выводе, так как appendFile не будет выдавать поток выполнения, пока вся операция не будет завершена.

Обратите внимание, что если appendFile использует буферизованный или линейный вывод, онзадержать запись чего-либо до тех пор, пока не будет вычислен фрагмент вывода.Если буферизация отключена, она должна выполнять системный вызов для каждого добавляемого вами символа, что очень медленно.

...