1

I am very new to Haskell and I have a problem. I have a module defined as:

inc :: Int->[Int]->[Int]

What it is supposed to do is to return all occurrences of the first argument in its second argument. So output of 1 [1,1,3] would return [1,1].

This is what I have:

 inc :: Int->[Int]->[Int]
 inc x [y] = if [x] == [y] then [x] else []

Since I was struggling I just wanted to see if it would work for one number and it does. For instance: 1 [1] returns [1]. However, when I attempt you use multiple values such as 1 [1,1] I receive the error:

Non exhaustive patterns in the function inc

How could I adapt my program, so it is able to handle multiple values instead of just one value?

melpomene
  • 84,125
  • 8
  • 85
  • 148
Cody G.
  • 53
  • 3
  • Do you understand what the error message is telling you? – Mark Seemann Sep 16 '18 at 01:57
  • From my understanding it means I'm missing a case. Possibly if [y] == []? @MarkSeemann – Cody G. Sep 16 '18 at 02:10
  • 3
    Note that, if we are not writing a type signature, `[y]` doesn't mean "a list called `y`", but rather "a list with a single element, `y`". You might want to have a look at [this question](https://stackoverflow.com/q/48884276/2751851). – duplode Sep 16 '18 at 02:23
  • 1
    @CodyG. Yes, that's one missing case. It's not the only one, though. – Mark Seemann Sep 16 '18 at 02:58
  • (By the way, the "if we are not writing a type signature" in my previous comment might give the wrong impression, as `[y]` on a type signature means something entirely different -- the type of lists with elements of some type `y`.) – duplode Sep 16 '18 at 03:21
  • @duplode thanks for the hhelp but I'm just really confused. I looked over your link and it makes sense that I can't use [y] however, I'm unsure of where to go after because I run in to a whole host of other errors such as couldn't match type [Int] with expected type Int. – Cody G. Sep 16 '18 at 03:35
  • Possible duplicate of [Non exhaustive pattern in function noThirds](https://stackoverflow.com/questions/23178455/non-exhaustive-pattern-in-function-nothirds) – jberryman Sep 16 '18 at 04:33
  • 1
    Your question is too broad (and I voted to close it as such). Start by making your function be able to also handle empty lists. then add ability to handle lists of two elements. if you have problems there, ask new specific questions please. see [mcve]. -- also see if [this](https://web.archive.org/web/20160728022441/http://stackoverflow.com:80/documentation/haskell/2281/lists) helps. – Will Ness Sep 16 '18 at 07:21
  • (change that last link to [this](https://web.archive.org/web/20170803134836/https://stackoverflow.com/documentation/haskell/2281/lists)). – Will Ness Sep 16 '18 at 07:35

4 Answers4

1

A list value can be of any one of the following forms

  • []
  • [y1], i.e. y1:[]
  • [y1,y2], i.e. y1:y2:[]
  • [y1,y2,y3], i.e. y1:y2:y3:[]
  • ...
  • infinite lists y1:y2:y3:...

(pedantically, we also have lists ending with a bottom, but I'll neglect those)

A defining equation like

f [y] = ...

only considers the lists of the form [y1], having a single element (y). All the other cases are not matched by the equation.

If y is meant to be a generic list argument, and not the single element, we instead must use

f y = ...

As we see, list arguments do not require special syntax.

To detect non-exhaustiveness errors, it is strongly recommended to turn on warnings during compilation. If we do so, GHC would report that we missed the cases [] and _:_:_, the latter being a list with at least two elements.

chi
  • 111,837
  • 3
  • 133
  • 218
0

Your implementation is incomplete, it says you are only supporting lists of single elements. You need to extend your implementation in order to cover all the possibilities. Use recursion to iterate through all the elements. A possible implementation could be:

inc :: Int->[Int]->[Int]
inc _ [] = []
inc x (y:ys) = if x == y then x:inc x ys else inc x ys
renatodamas
  • 16,555
  • 8
  • 30
  • 51
0

When you want to inspect values of some type, you need to know what the possible "shapes" (i.e. data constructors) of that type are.

In the case of lists, values have one of two forms:

  • empty: []
  • non-empty: h : t (where h is the head (first element) of the list and t is the tail (another list))

When you write something like [1, 2, 3], it really means 1 : (2 : (3 : [])) (a list whose head is 1 and whose tail is another list whose head is 2 and whose tail is another list whose head is 3 and whose tail is []).

For functions consuming lists, that usually means you need to provide two equations:

inc x [] = ...

to handle empty lists and

inc x (y : ys) = ...

to handle non-empty lists (y will be the first element of the list and ys the remaining values).

melpomene
  • 84,125
  • 8
  • 85
  • 148
0

In Haskell, when possible its best to avoid explicit recursion and do away with some of the exhaustive pattern matching by using functions. Specifically for this case, you could use filter. Read up on its documentation here

Using this function your program could be written as:

inc :: Int-> [Int] -> [Int]
inc x ys = filter (==x) ys

Or point free style:

inc x = filter (==x)
dopamane
  • 1,315
  • 2
  • 14
  • 27