1

I'm working on a function for a homework problem that counts the number of values in a list for which the values are greater than v1 and less than v2. I've put something together that works but only in a specific case. When I try something else I get the error of

*** Exception: Non-exhaustive patterns in function countInRange

This function is supposed to call on getInRange. getInRange just returns values from a list that are greater than v1 and less than v2. Here is what it looks like.

rangeHelper v1 v2 x | x > v1 && x < v2 = True
                    | otherwise = False

getInRange :: Ord a => a -> a -> [a] -> [a]
getInRange v1 v2 iL = filter(rangeHelper v1 v2) iL

count iL = sum (map (const 1) iL)

countInRange :: Ord a => a -> a -> [[a]] -> Int
countInRange v1 v2 [iL] = count ((getInRange v1 v2) iL)

If I were to call

countInRange 3 10 [[4,5,6]]         -- works, prints 3
countInRange 3 10 [[1,2], [4,5,6]]  -- error: non exhaustive patterns
Will Ness
  • 70,110
  • 9
  • 98
  • 181
Larry.Fish
  • 123
  • 1
  • 8
  • 3
    `countInRange v1 v2 [iL]` should be `countInRange v1 v2 iL` (no square brackets, your version only applies to a singleton list, whose member is itself a list of numbers). Unless you really want it to accept a list of lists, but that (even with the input that "works") looks quite strange to me. – Robin Zigmond Sep 26 '19 at 06:57
  • Well the requirement is that I need to pass in two values and a nested list because I need to be able to work on the lists within the list. – Larry.Fish Sep 26 '19 at 07:21
  • 1
    (Minor style point: `rangeHelper v1 v2 x = x > v1 && x < v2` is simpler. Don't check if a boolean value is true/false only to return the exact same value.) – chi Sep 26 '19 at 07:32
  • 1
    I don't completely understand your goal. What is the expected result of `countInRange 3 10 [[1,2],[3,40]]`? Three? So, in general `countInRange 3 10 [[a,b],[c,d]]` must be the same as `countInRange 3 10 [[a,b,c,d]]`? If so, consider `concat`enating the list of lists into a single list before counting. – chi Sep 26 '19 at 07:37
  • The goal would be to print the value of 3 when I call countInRange 3 10 [[1,2], [4,5,6]] because 4,5,6 are the only values that are greater 3 and less than 10. – Larry.Fish Sep 26 '19 at 07:55

2 Answers2

3

If we were to simplify your function even to just

countInRange v1 v2 [ iL ]  =  0

we would still observe the same behavior:

countInRange 3 10 [ [4,5,6]        ]   -- returns 0
countInRange 3 10 [ [1,2], [4,5,6] ]   -- ***Error: Non-exhaustive patterns

Can you see the problem, here?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • The answer is much better with your edit. StackOverflow at its best (imho). And thanks to you. – Micha Wiedenmann Sep 26 '19 at 08:56
  • just a little copy editing, is all. :) the main idea is yours. and you're welcome. this reminds me of [tag:failure-slice]: to see the problem clearer, minimize the code as much as possible while it still exhibits the same problematic behaviour. – Will Ness Sep 26 '19 at 14:15
  • 1
    I call it minimization or test case generation and it is my favorite/go-to debugging technique. – Micha Wiedenmann Sep 26 '19 at 14:16
2

Your countInRange function only expects a list that contains one list. When you write countInRange v1 v2 [iL] you only define it to match pattern when your list contains single element called iL. You can also use count = length

You can fix this issue by defining it like this:

countInRange v1 v2 xs  = sum (map (length.filter (rangeHelper v1 v2)) xs)
-- or
countInRange v1 v2     = sum.map (length.filter (rangeHelper v1 v2))
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Yogendra
  • 372
  • 3
  • 10
  • 3
    Instead of filtering & counting each list, and then summing the counts, I think it's simpler to concatenate, filter, and then count, as in `length . filter (rangeHelper v1 v2) . concat`. – chi Sep 26 '19 at 12:13
  • @chi sure, that would be a better solution, I was just trying to change as little as possible in the existing solution – Yogendra Sep 26 '19 at 14:42