So I have a function that takes a character and a list of tuples [tuple is a pair containing a character and an integer]. If the character matches the tuple character, the corresponding number is incremented by one. If not, then the tuple is printed as is.
So basically
foo 'a' [('a',1),('b',2),('c',1)]
Should yield
[('a',2),('b',2),('c',1)]
I have written the following code, but understandably, it skips printing over the last tuple:
foo a ((x,y):xs) | xs == [] = []
| x==a = (x,y 1):foo a xs
| x/=a = (x,y):foo a xs
foo 'a' [('a',1),('b',2),('c',1)]
O/P : [('a',2),('b',2)]
How do I modify the function such that it considers the last tuple too? I'd also like to be able to add a tuple with a count of 1 if the element is not present in the list of tuples
CodePudding user response:
Note what happens if we try to apply foo to the empty list:
λ> foo 'a' []
*** Exception: <interactive>:(90,1)-(92,40): Non-exhaustive patterns in function foo
It is generally frowned upon to use guards for things you can pattern match. Let's rewrite foo a bit, hopefully, it will make the cause of the exception clear and help you see what should be do to fix the problem:
foo _ (_:[]) = [] -- the pattern could also be `[_]`
foo a ((x,y):xs) | x==a = (x,y 1):foo a xs
| x/=a = (x,y):foo a xs
Now it's evident one element lists are discarded:
λ> foo 'a' [('a',1)]
[]
Let's this. Also, the guard forces us to replicate work, let's remove it.
foo _ [] = []
foo a ((x,y):xs) = (x, if x == a then y 1 else y):foo a xs
And voilà:
λ> foo 'a' []
[]
λ> foo 'a' [('a',1)]
[('a',2)]
λ> foo 'b' [('a',1),('b',2),('c',3)]
[('a',1),('b',3),('c',3)]
CodePudding user response:
Your xs == []
case needs to be done at the same level as the pattern match, not after it.
foo :: a -> [(a, Int)] -> [(a, Int)]
foo _ [] = []
foo a ((x, y):xs)
| x==a = (x, y 1) : foo a xs
| otherwise = (x, y ) : foo a xs
Your version only checks that the tail (excluding the first element) is empty. You want to check if the whole list is empty and handle that case differently.
Side note: If you compile Haskell with -Wall
, it will warn you about the partial function. I recommend always using -Wall
. 99% of the things it warns you about are genuinely good advice, and the handful of silly warnings can be easily disabled on-demand.