1

I made this code for removing common elements in a list but it only worked for integers list i have an example for

remove [ A "List", A "List", A "Gone", A "Still"]

it must give as an output [ A "List", A "Gone", A "Still"] it doesn't work gives an undefined constructor A

remove [] = []
remove (x:xs) | x `elem` xs = remove xs
              | otherwise = x : remove xs
7
  • 1
    Well syntax highlighting here already revelals one of the issues. But there are some other issues, for example, it can not process an infinite list at all (unless it only contains duplicates, but then it will keep searching for the first non-duplicate). Commented Apr 19, 2018 at 16:39
  • 1
    What is A supposed to be here? Of course the compiler doesn't know what you're talking about, if A isn't defined! Commented Apr 19, 2018 at 16:40
  • Then how can I edit the code if i want it to work for a list like the one above Commented Apr 19, 2018 at 16:41
  • @IslamNasr Define A, or remove it. I don't know what you want it to be, but you probably want this line: data A = A String deriving (Eq, Show). Commented Apr 19, 2018 at 16:42
  • @AJFarmer ill try it now Commented Apr 19, 2018 at 16:45

1 Answer 1

3

The issue here is not per se the function itself, but the input list:

remove [ A "List", A "List", A "Gone", A "Still"]

It contains a list of elements, each element has the data constructor A followed by a string. In some languages like Prolog, one can dynamically introduce functors, but not in Haskell: Haskell is statically typed, and as a result you need to declare the types. We can for instance declare the type:

data A = A String deriving (Eq, Show)

Now we declared a type A, where there is a single data constructor A that takes as parameter a String. We made it deriving (Eq, Show), such that two As are equal, given they have the same data constructor (but since there is only one, this is always the case), as well as the fact that the parameter should be the same. The Show enables us to print A instances.

So now it will at least produce output (not generate a compiler error). But the function itself still has a potential problem: here you check membership in the tail of ther list. There can be two problems with that:

  1. we will always keep the last occurrence, so remove [1, 4, 1, 2] will return [4, 1, 2], whereas we probably want to return [1, 4, 2]; and
  2. in case we process an infinite list, then for non-duplicate elements, elem, will keep looking for a duplicate. As a result eventually Haskell will run out of memory and crash.

We better use an accumulator here that stores the elements thus far observed, and call elem on that list, like:

remove :: Eq a => [a] -> [a]
remove = go []
    where go _ [] = []
          go seen (x:xs) | elem x seen = go seen xs
                         | otherwise = x : go (x:seen) xs
Sign up to request clarification or add additional context in comments.

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.