0

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).

cjr
  • 520
  • 2
  • 7
  • 22

4 Answers4

6

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.

Community
  • 1
  • 1
András Kovács
  • 29,931
  • 3
  • 53
  • 99
  • That is awesome! Thank you! I did not know about the filter function but that is going to save me a lot of hassle in the future! – cjr Nov 05 '13 at 19:17
0

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]
Ankur
  • 33,367
  • 2
  • 46
  • 72
0

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)
yatima2975
  • 6,580
  • 21
  • 42
0

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)
viorior
  • 1,783
  • 11
  • 16