Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
module Automata where
import Prelude hiding (map, head, foldl, take)
import qualified Prelude as P
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import Data.ByteString.Internal (c2w)
import qualified Data.Map as M
import Data.List (sort)
import Data.Tuple
import System.Environment
import Data.Enumerator hiding (foldl)
import Data.Enumerator.List
import qualified Data.Enumerator.Binary as EB
-- Data Types
data Entry = Entry {
date :: BS.ByteString,
host :: BS.ByteString,
program :: BS.ByteString,
message :: BS.ByteString
} deriving Show
type Summary = M.Map BS.ByteString Int
-- Enumerator
filelines :: FilePath -> Enumerator BS.ByteString IO a
filelines fname = EB.enumFile fname $= EB.splitWhen (==(c2w '\n'))
-- Iteratees
count :: Monad m => Iteratee BS.ByteString m Int
count = (fold (flip $ const (+1)) 0)
summary :: Monad m => Iteratee BS.ByteString m Summary
summary = fold op M.empty
where op :: Summary -> BS.ByteString -> Summary
op sumMap line =
let e = parseEntry line
in M.insertWith' (+) (program e) 1 sumMap
-- Utils
parseEntry :: BS.ByteString -> Entry
parseEntry s = Entry d h p m
where d1:d2:d3:h:p':ms = C.words s
d = C.unwords [d1,d2,d3]
p = BS.init p'
m = C.unwords ms
top10 :: Summary -> [(Int, BS.ByteString)]
top10 = P.take 10 . P.reverse . sort . swap . M.toList
processFile :: Enumerator BS.ByteString IO (Int, Summary) -> IO (Int, [(Int, BS.ByteString)])
processFile enum = do
(i, sum) <- run_ $ enum $$ count summary
return (i, top10 sum)
main = do
fname <- getArgs >>= return . P.head
print =<< (processFile $ filelines fname)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.