Create a gist now

Instantly share code, notes, and snippets.

import Data.Enumerator hiding (map, length, foldl)
import qualified Data.Enumerator.Text as ET
import qualified Data.Enumerator.List as EL
import Data.List (sort)
import qualified Data.Map as M
import Data.Text (Text)
data Entry = Entry { date :: String
, host :: String
, program :: String
, message :: String
} deriving Show
processFile :: IO ()
processFile = run_ syslogIteratee >>= print
-- iteratees et al.
syslogIteratee :: Iteratee Entry IO ([(Int, String)], Int)
syslogIteratee = entryEnumerator $$ entryIteratee
entryEnumerator :: Enumerator Entry IO b
entryEnumerator = syslogEnumerator $= entryParser
syslogEnumerator :: Enumerator Text IO b
syslogEnumerator = ET.enumFile "syslog"
entryIteratee :: Monad m => Iteratee Entry m ([(Int, String)], Int)
entryIteratee = EL.zipWith top10AndId summariser counter
entryParser :: Monad m => Enumeratee Text Entry m b
entryParser = EL.map parseEntry
summariser :: Monad m => Iteratee Entry m (M.Map String Int)
summariser = EL.fold updateSummary M.empty
where updateSummary summary entry = M.insertWith' (+) (program entry) 1 summary
counter :: Monad m => Iteratee a m Int
counter = EL.fold (\acc _ -> acc + 1) 0
-- auxiliary functions
parseEntry :: Text -> Entry
parseEntry text = Entry d h p m
where d1:d2:d3:h:p':ms = words $ show text
d = unwords [d1,d2,d3]
p = init p'
m = unwords ms
top10AndId :: Ord a => M.Map a Int -> b -> ([(Int, a)], b)
top10AndId m b = (top10 m, b)
top10 :: Ord a => M.Map a Int -> [(Int, a)]
top10 = take 10 . reverse . sort . map swap . M.toList
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment