Search code examples
haskellpattern-matchingnon-exhaustive-patterns

Non-exhaustive patterns in function


I've got a problem with this code, it should count the longest substring of the same letter in a string, but there is an error:

*** Exception: test.hs:(15,0)-(21,17): 
Non-exhaustive patterns in function countLongest'

I know that is the wrong types problem, but i dont know where is the error, or how to find or debug it

countLongest :: (Eq a) => [a] -> Int
countLongest' :: (Eq a) => Int -> Int -> [a] -> Int

countLongest a = countLongest' 0 0 a
countLongest' n max (y:x:ys)
        | y == x = countLongest' (n+1) max (x:ys)
        | n > max = countLongest' 0 (n) (x:ys)
        | otherwise = countLongest' 0 (max) (x:ys)
countLongest' n max []
        | n > max = n
        | otherwise = max

Solution

  • It looks like you're missing the case where there's a one element list:

    countLongest' n max (y:ys)
        | ... etc. ...
        | otherwise = ....
    

    Here's a contrived example similar to yours:

    f [] = 3         -- matches an empty list
    f (a:b:bs) = 4   -- matches a list with at least two elements
    

    Examples:

    Prelude> :load myfile.hs 
    [1 of 1] Compiling Main             ( myfile.hs, interpreted )
    Ok, modules loaded: Main.
    *Main> f [3]
    *** Exception: myfile.hs:(3,0)-(4,13): Non-exhaustive patterns in function f
    
    *Main> f []
    3
    *Main> f [1,2,3,4,5]
    4
    *Main> 
    

    So it succeeds with 0 and 2 elements in the list, but fails when there's exactly one element.


    Note that this behavior is not unique to lists. Here's an example using Maybe:

    g :: Maybe x -> x
    g (Just x) = x
    

    Examples:

    *Main> g (Just 4)
    4
    *Main> g Nothing 
    *** Exception: myfile.hs:6:0-13: Non-exhaustive patterns in function g
    

    This happened because there's two constructors for Maybe, Just <something> and Nothing. We didn't provide a case for Nothing, so when we passed that into g, it didn't work!


    Check out this question and its answers for information on getting a little help from the compiler. I followed the advice of the first answer, and when I loaded my examples, this is what happened:

    prompt$ ghci -fwarn-incomplete-patterns
    
    Prelude> :load myfile.hs 
    [1 of 1] Compiling Main             ( myfile.hs, interpreted )
    
    myfile.hs:3:0:
        Warning: Pattern match(es) are non-exhaustive
                 In the definition of `f': Patterns not matched: [_]
    
    myfile.hs:6:0:
        Warning: Pattern match(es) are non-exhaustive
                 In the definition of `g': Patterns not matched: Nothing
    Ok, modules loaded: Main.
    

    Cool! The compiler is pretty smart!