2
votes

So I'm trying to match this pattern. MessageType is a type that I've created. This function takes in a string, and then depending on the first character of that string, it outputs a MessageType. Whenever I compile though, I get a warning saying:

 Pattern match(es) are non-exhaustive
    In an equation for ‘parseMessage’: Patterns not matched: []

Here's my code:

parseMessage :: String -> MessageType
parseMessage (x:_)
  | x == 'I'      = Info
  | x == 'W'      = Warning
  | otherwise     = Error 1

How is it that my pattern matches aren't exhaustive? Wouldn't the otherwise guard catch anything else? I don't see how my function fails to catch all strings.

When I write the function like this, I do not get the warning.

parseMessage []     = error "Empty String"
parseMessage (x:_) = if x == 'I'
                        then Info
                        else if x == 'W'
                        then Warning
                        else Error 1

I rewrote my function this way because I saw that the warning says "Patterns not matched: []", so I explicitly handled it. But why is it that in the first version of my function, it says that the pattern is not handled. How does otherwise not catch everything besides the first two guards?

2

2 Answers

12
votes

Guards are specific to a single pattern case in a function’s definition, so when you write this:

parseMessage (x:_)
  | x == 'I'      = Info
  | x == 'W'      = Warning
  | otherwise     = Error 1

…your guards won’t even be consulted if you run parseMessage "". The (x:_) pattern would fail, so all of its guards are ignored. This needs to be the case in order for x to be bound within the guard conditions.

To fix this, you just need to add a case that handles the empty string:

parseMessage :: String -> MessageType
parseMessage ""   = Error 1
parseMessage (x:_)
  | x == 'I'      = Info
  | x == 'W'      = Warning
  | otherwise     = Error 1

Now you’ve handled all possible cases.

8
votes

Why not write directly...

parseMessage ('I':_) = Info
parseMessage ('W':_) = Warning
parseMessage _       = Error 1