5
votes

I have a question regarding Haskell that's been stumping my brain. I'm currently required to write a function that removes a string i.e. "word" from a list of strings ["hi", "today", "word", "Word", "WORD"] returns the list ["hi", "today", "Word", "WORD"]. I cannot use any higher-order functions and can only resort to primitive recursion.

Thinking about the problem, I thought maybe I could solve it by using a recursion where you search the head of the first string, if it matches "w" then compare the next head from the tail, and see if that matches "o". But then I soon realized that after all that work, you wouldn't be able to delete the complete string "word".

My question really being how do I compare a whole string in a list rather than only comparing 1 element at a time with something like: removeWord (x:xs). Is it even possible? Do I have to write a helper function to aid in the solution?

4
The fact that your list contains strings isn't really important here. Try solving the problem for e.g. list of Int first, then it should be just a matter of changing the type signature to make it work for lists of strings.hammar
When you match (x:xs) against ["hi", "today", "word", "Word", "WORD"], x becomes "hi" and xs becomes ["today", "word", "Word", "WORD"]. That is, it matches string by string, not character by character. This works because you have a list of strings rather than just one big string.Tikhon Jelvis
Oh I see! Thank you so much this is where it was giving me trouble. I thought it was only the first element and not the whole word. This clears up everything!Phirip

4 Answers

3
votes

Consider the base case: removing a word from an empty list will be the empty list. This can be trivially written like so:

removeWord [] _ = []

Now consider the case where the list is not empty. You match this with x:xs. You can use a guard to select between these two conditions:

  1. x is the word you want to remove. (x == word)
  2. x is not the word you want to remove. (otherwise)
3
votes

You don't need a helper function, though you could write one if you wanted to. You've basically got 3 conditions:

  1. You get an empty list.
  2. You get a list whose first element is the one you want to remove.
  3. You get a list whose first element is anything else.

In other languages, you would do this with a set of if-else statements, or with a case statement, or a cond. In Haskell, you can do this with guards:

remove_word_recursive:: String -> [String] -> [String]
remove_word_recursive _ []                              = []
remove_word_recursive test_word (x:xs) | test_word == x = what in this case?
remove_word_recursive test_word (x:xs)                  = what in default case?

Fill in the correct result for this function in these two conditions, and you should be done.

I think what you're looking for is a special case of the function sought for this question on string filters: Haskell - filter string list based on some conditions . Reading some of the discussion on the accepted answer might help you understand more of Haskell.

3
votes

Since you want to remove a list element, it's easy to do it with List Comprehension.

myList = ["hi", "today", "word", "Word", "WORD"]
[x | x <- myList, x /= "word"]

The result is:

["hi","today","Word","WORD"]
0
votes

If isInfixOf is not considered as higher order, then

import Data.List (isInfixOf)
filter  (not . isInfixOf "word")  ["hi", "today", "word", "Word", "WORD"]