У меня есть эта функция для ленивого просмотра файла журнала ...
follow :: Handle -> IO [String]
follow h = unsafeInterleaveIO $ do
catch (do line <- hGetLine h
lines <- follow h
return $ line : lines)
(const (do threadDelay (1000 * 100)
follow h))
... это здорово, потому что он возвращает бесконечный список, который можно обрабатывать построчно при добавлении файла журнала, например:
h <- openFile "test.log" ReadMode
ls <- follow h
mapM_ putStrLn ls
Но теперь мне нужно объединить несколько строк перед их обработкой. (Некоторые записи журнала разделены на несколько строк в формате xml, которые мне нужно собрать вместе). Я попробовал следующее, чтобы сделать это, но оно никогда не завершается, потому что follow
никогда не завершается, как я понимаю.
h <- openFile "test.log" ReadMode
ls <- follow h
mapM_ putStrLn (concatWhen (isPrefixOf "foo") ls)
concatWhen :: (String -> Bool) -> [String] -> [String]
concatWhen _ [] = []
concatWhen p as = let (xs, as') = span p as
(ys, rest) = break p as'
in (concat xs) : ys ++ (concatWhen p rest)
Есть ли хороший способ сделать это? Нужно ли выполнять соединение строк в follow
, или есть более элегантный способ работы с массивом строк, возвращаемым этой функцией?
Если это имеет какое-либо значение, можно определить, является ли строка последней из группы, требующей объединения, путем проверки содержимого.