0

I have a first list and a second list, and I want to write a function that takes two lists and returns a list containing only those elements in the second list that do not appear in the first. And I don't want to use built-in functions. For example:

> removeAll [1..3] [0..10]
[0,4,5,6,7,8,9,10]

> removeAll "aeiou" "supercalifragilisticexpialidocious"
"sprclfrglstcxpldcs"

removeAll _ [] = [] 
removeAll [] y = y

removeAll (x:xs) (y:ys)
    | x==y = removeAll xs ys
    | otherwise = y:removeAll xs ys
2
  • 1
    What is your question? Commented Nov 22, 2018 at 5:43
  • 3
    You can always look at the source of the built-in functions, so you shouldn't count those out. Commented Nov 22, 2018 at 5:44

3 Answers 3

1

This is one simple way:

removeAll ignores = filter (\x -> notElem x ignores)

which makes use of:

If you wanted to write it in "pure-pure" Haskell, with no auxiliary functions... well, it sounds like it would be pretty ugly since we'd need to do some sort of nested for-loop. Here's a compromise:

myFilter _ [] = []
myFilter pred (x:xs)
  | pred x = x : myFilter pred xs
  | otherwise = myFilter pred xs

myNotElem e [] = True
myNotElem e (x:xs)
  | e == x = False
  | otherwise = myNotElem e xs

removeAll ignores = myFilter (\x -> myNotElem x ignores)
Sign up to request clarification or add additional context in comments.

Comments

0

There is a pretty straightforward recursive definition

removeAll :: Eq a => [a] -> [a] -> [a]
removeAll _        []     = []
removeAll toRemove (x:xs) 
  | x `belongs` toRemove = removeAll toRemove xs 
  | otherwise            = x:removeAll toRemove xs 
    where belongs _ [] = False
          belongs a (y:ys)
            | a == y    = True
            | otherwise = belongs a ys 

The belongs function is just the prelude defined elem. Since you don't want to use built-in functions you have to define it yourself.

Comments

0

A problem of your current code is that you tried to recurse in two lists simultaneously in one function. You need to divide and conquer. If elem is allowed, you may write:

removeAll :: Eq a => [a] -> [a] -> [a]
removeAll _ [] = []
removeAll x (y:ys)
    | myElem y x = removeAll x ys
    | otherwise = y:removeAll x ys

If you do not want to use the built-in elem as well, you can define it similarly:

myElem :: Eq a => a -> [a] -> Bool
myElem _ [] = False
myElem x (y:ys)
    | x == y = True
    | otherwise = myElem x ys

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.