Lazy ByteString - странное поведение или ошибка?

Когда я тестирую свою функцию intervalFinder в GHCI, кажется, что она работает, но когда я пытаюсь ее скомпилировать, у меня НЕТ вывода:

Функция работает на входе:

*Main> intervalFinder $[B.pack"first",B.pack"second",B.empty,B.pack"third",B.emp
ty]
Loading package bytestring-0.9.2.1 ... linking ... done.
["Start Time: first","End   Time: second","Start Time: third","End   Time: third
"]

И работает main:

*Main> main
Loading package bytestring-0.9.2.1 ... linking ... done.
*Main> :q
Leaving GHCi.

печатает в results.txt:

Start Time: firstEnd   Time: secondStart Time: thirdEnd   Time: third 

но если я запустил ghc test3.hs, выходной файл будет 0kb (и, очевидно, в нем нет данных!)

Я делаю что-то неправильно?

Код:

{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as Bl
import System.IO 
import System.Environment


intervalFinder :: [B.ByteString]->[B.ByteString]
intervalFinder x = helper x ""
    where
    helper (x:xs) "" 
        | x /= ""   = ((B.append (B.pack("Start Time: ")) x)):(helper xs x)
        | otherwise = helper xs ""
    helper (x:xs) y
        | x == ""   = ( (B.append (B.pack("End   Time: ")) y)):(helper xs "")
        | otherwise = helper xs x
    helper _ _      = []

main = do
    filehandle <- openFile "result.txt" WriteMode
    Bl.hPutStr (filehandle) .  Bl.fromChunks . intervalFinder $[B.pack"first",B.pack"second",B.empty,B.pack"third",B.empty]

Спасибо!


person MdxBhmt    schedule 30.08.2012    source источник


Ответы (1)


main = do
    filehandle <- openFile "result.txt" WriteMode
    Bl.hPutStr (filehandle) .  Bl.fromChunks . intervalFinder
          $[B.pack"first",B.pack"second",B.empty,B.pack"third",B.empty]

Вывод буферизируется, поэтому программа выходит без очистки буфера с помощью runghc или скомпилированного двоичного файла. В ghci все буферы очищаются при выходе из ghci¹.

Когда вы openFile обрабатываете дескриптор файла, вы должны hClose это делать после использования. Это также очищает выходной буфер, если он открыт в режиме записи или добавления.

main = do
    filehandle <- openFile "result.txt" WriteMode
    Bl.hPutStr (filehandle) .  Bl.fromChunks . intervalFinder
          $[B.pack"first",B.pack"second",B.empty,B.pack"third",B.empty]
    hClose filehandle

В качестве альтернативы вы можете использовать writeFile

main = Bl.writeFile "result.txt" $ Bl.fromChunks ...

¹ Я не уверен в этом на 100%, но опыт подтверждает это.

person Daniel Fischer    schedule 30.08.2012
comment
Это сработало! Я застрял, потому что до того, как вставить инверфалфиндер, код работал нормально (у меня была карта (Bl.pack. B.unpack) на месте) и я не мог понять, почему один работал, а другой нет. - person MdxBhmt; 31.08.2012
comment
Код hClose небезопасен (может привести к утечке дескриптора в случае исключений). Для этого withFile. - person Peaker; 31.08.2012