Search code examples
haskellfunctional-programmingnon-exhaustive-patterns

Non-exhaustive patterns, Haskell


I am trying to write the function tails, which converts a string into a list of strings in the following way:

tails "abc" = ["abc", "bc", "c", ""]

Here is my implementation:

tails :: [Char] -> [[Char]]
tails (x:xs)
  | length (x:xs) == 0 = [""]
  | otherwise = (x:xs) : tails xs

As the title suggests, there are non-exhaustive patterns in this function. Unfortunately, I don't see how so.

I am new to Haskell... Any help would be appreciated!


Solution

  • The pattern is non-exhaustive because it can't accept []. A list has form of either [] or a:as, where a is the leading element and as is the list of the trailing elements. So the pattern x:xs matches only if the list has a leading element. Fixing that gives:

    tails :: [Char] -> [[Char]]
    tails xs
        | length xs == 0 = [""]
        | otherwise = let (_:xs') = xs in xs : tails xs'
    

    And then xs accepts the list regardless of its form. But this is inefficient due to length, and doesn't work for infinite lists.

    This should fully work, which directly does pattern mathing:

    tails :: [Char] -> [[Char]]
    tails [] = [""]
    tails xs@(_:xs') = xs : tails xs'