Search code examples
haskellpattern-matchingguard-clause

patterns vs. guards: otherwise does not match?


The following two functions behave differently when given an empty string:

guardMatch l@(x:xs) 
    | x == '-'        = "negative " ++ xs
    | otherwise       = l

patternMatch ('-':xs) = "negative " ++ xs
patternMatch l        = l

Here my output:

*Main> guardMatch ""
"*** Exception: matching.hs:(1,1)-(3,20): Non-exhaustive patterns in function guardMatch

*Main> patternMatch ""
""

Question: why does not the 'otherwise' close catch the empty string?


Solution

  • The otherwise is within the scope of the pattern l@(x:xs), which can only match a non-empty string. It might help to see what this (effectively) translates to internally:

    guardMatch   l = case l of
                       (x  :xs) -> if x == '-' then "negative " ++ xs else l
    patternMatch l = case l of
                       ('-':xs) ->                  "negative " ++ xs
                       _        ->                                         l
    

    (Actually, I think the if is translated to a case + guard instead of the other way around.)