Skip to content

Instantly share code, notes, and snippets.

@mmakowski
Created November 27, 2011 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmakowski/1397756 to your computer and use it in GitHub Desktop.
Save mmakowski/1397756 to your computer and use it in GitHub Desktop.
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