Exception: Non-exhaustive Patterns in Function - Haskell

Asked

Viewed 244 times

1

I’m trying to make a code in Haskell that eliminates all repeated values from a list, the code is like this:

import Data.List

filtraLista [] = []
filtraLista (xs : []) =  [xs]
sort filtraLista (x:y:xs)
  |x == y = filtraLista (y : xs)
  |otherwise = x : filtraLista (y : xs)

Code compiles but does not work, error always appears:

*** Exception: main.hs:(3,1)-(4,29): Non-exhaustive Patterns in Function filtraLista

I can’t identify which error

3 answers

2

This function reminds me the nub that is already set in Haskell to do just this would not solve the problem?

import Data.List

filtraLista [] = []
filtraLista [x] = [x]
filtraLista (x:xs) = x : filter (/= x) (filtraLista xs)

1

This error happens when it is not possible to match the function input with any of the defaults defined for the function, and this happened because there is an error in the fourth line of your program.

In the fourth line you write

sort filtraLista (x:y:xs)

meaning that you are defining a function called sort of two arguments, which were called filtraLista and (x:y:xs), which, the right thing would be for you to write something like

filtraLista sort (x:y:xs)

because then yes, you would be continuing the definition of filtraLista. However, if you write this, a different error will happen:

Equations for `filtraLista' have Different Numbers of Arguments

which happens because the first two patterns result in a function of an input argument, while the latter results in one of two input arguments.

So you can set the function correctly, I have a suggestion:

  1. Write filtraLista assuming that the entry lists will be always ordered. That way, you don’t need to use sort.
  2. I renamed it filtraLista for filtraHelper. And then define filtraLista as being filtraHelper receiving the argument of filtraLista already ordered, that is to say: filtraLista xs = filtraHelper (sort xs).
  3. User where to incorporate the definition of filtraHelper inside filtraLista so that the end user does not have access to it:
filtraLista xs = filtraHelper (sort xs)
  where filtraHelper ...

This practice is called worker wrapper and is quite common in Haskell. You can read more about this here (in English).

Finally, one question you may have is:

If there’s a sort which was imported from Data.List, how it was possible to define a new sort? Shouldn’t it have caused a build error? What happened to Data.List?

It is possible, yes, to override imported functions. However, they will always be available by their full name (the usual term is "qualified name", or even "fully qualified name"). That is, even if you create a new sort, for the imported version to be accessed you must write Data.List.sort. To better understand how module import works I recommend the chapter "Modules" of LYHFGG (read here in English).

1

You defined filtraLista for empty list and also with an element, but was missing for two or more elements, hence the Non-exhaustive patterns. On line 5, you started by saying that the function name was sort instead of filterList.

I refactored the function a little bit and it was like this:

import Data.List

filtraLista [] = []
filtraLista (x : []) =  [x]
filtraLista lista =
  let
    (x:y:xs) = sort lista
  in
    if x == y
      then filtraLista (y : xs)
      else x : filtraLista (y : xs)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.