UPenn CIS 194 Homework 2: Log file parsing
parseMessage

The main problem here is that you are calling unwords on the result of words ..., and this doesn't preserve the original whitespace.

For instance, the last case should just be:

case words x of
   ...
   _   -&gt; Unknown x   -- use the original message text


and you have a similar problem with unwords m.

Unfortunately, to preserve whitespace in these cases I don't think you will be able to use the words function here.

It is customary to have parens around the list patterns, e.g.:

parseMessage x = case words x of
                      ("E":s:t:m) -&gt;  LogMessage (Error (read s::Int)) (read t::Int) (unwords m)


Even though they are not needed, they aid in reading the code.

Also, aligning the -&gt; in the case patterns helps with readability.

The type signatures on your read calls are not needed due to Haskell's type inference.

insert

You should be getting this warning from ghc and ghci:

LogAnalysis.hs:19:1: Warning:
    Pattern match(es) are non-exhaustive
    In an equation for ‘insert’:
        Patterns not matched:
            (LogMessage _ _ _) (Node (Node _ _ _) (Unknown _) _)
            (LogMessage _ _ _) (Node Leaf (Unknown _) _)


This means that your code doesn't cover all of the possible cases.

Append to your question an updated version of insert which doesn't produce any warnings, and then I might have some further comments about it.

(Please append to your question instead of modifying it so it doesn't invalidate any existing comments.)

Let me know if you are not seeing this warning from ghc / ghci so we can figure out what's going on with your environment.

filterEmpty

I don't think the logic is right here. What if you have this message:

LogMessage (Error 62) 23 ""


Shouldn't the empty message be included in the message list?