0
votes

Good day!

So I am trying to write a function is Haskell as follows

remove_nulls :: [ ([String], Int) ] -> [ ([String], Int) ] -> [ ([String], Int) ]
remove_nulls listofpair (y:ys)
| null listofpair = (y:ys)
| null (fst(head listofpair))= remove_nulls (tail listofpair) (y:ys)
| otherwise = remove_nulls (tail listofpair) (y:(head listofpair):ys)

Which takes an input that may looks like this

remove_nulls [ ([],0) , (["abc", "dce"], 2) ] []

The idea is that it will remove the tuple from the list if it contains a null in its first value. However, every time I call it it returns "Non-exhaustive patterns in function remove_nulls".

I've tried changing the base case but I always get the same result. Any help and exploitation would be great (currently just learning Haskell).

4
What should happen if the second argument is []? - Mikhail Glushenkov
Please give some examples of inputs and expected outputs. You are taking, as input, two lists of tuples. - Aaron McDaid

4 Answers

6
votes

If you just want to remove all the pairs with null first fields,

removeNulls xs = filter (not . null . fst) xs

will do exactly that. If you're not already familiar with the notation in (not . null . fst), it is just a shorter way to write the function \pair -> not (null (fst pair)). See this SO question for some more explanation.

Your original function seems to try inserting the good elements from the first list just after the first element of the second input list, and fails to work because it doesn't cover the case where the second list is empty.

0
votes

remove_nulls should take the list and return a new list hence:

remove_nulls :: [ ([String], Int) ] -> [ ([String], Int) ]
remove_nulls lst = [(x,y) | (x,y) <- lst, (not.null) x]
0
votes

Because you call remove_nulls with an empty list as the second argument, and you only provide a definition for when the second argument has at least one element (this is the (y:ys) pattern on the first line), no match can be found, leading to the error message you see.

I think (but haven't tried) that if you get rid of the y: matches, it should compile (but maybe not yet do what you want!). So try something like this instead:

remove_nulls :: [ ([String], Int) ] -> [ ([String], Int) ] -> [ ([String], Int) ]
remove_nulls listofpair ys
  | null listofpair = ys
  | null (fst (head listofpair))= remove_nulls (tail listofpair) ys
  | otherwise = remove_nulls (tail listofpair) (head listofpair:ys)
0
votes

You miss to add one extra condition: when second list is empty

remove_nulls :: [([a], t)] -> [([a], t)] -> [([a], t)]
remove_nulls [] ys = ys
remove_nulls (([], _):xs) ys = remove_nulls xs ys
remove_nulls (x:xs) [] = remove_nulls xs [x]       -- new condition
remove_nulls (x:xs) (y:ys) = remove_nulls xs (y:x:ys)