Tibério
Tibério

Reputation: 31

Learning Haskell: Making a function that returns a list of elements that only appear once

I'm learning Haskell and I'm trying to make a recursive function that receives a List of integers and returns a List of integers that only appears once in the list ( once :: [Int] -> [Int] ), so, for example, if the input list is [4, 8, 1, 5, 1, 6, 2, 3, 4, 2] the return would be [8, 5, 6, 3] , but I'm having some problems making the code, in how to make this into a recursive function.

I'm also trying to make it using list comprehension, I'm currently reading about it on Learn You A Haskell, but um also stuck, so if you also have an idea on how to make it using list comprehension I would be thankful to see how both implementations work.

Edit:

once [] = []
once (x:xs)
             | (x `notElem` xs) = x : once xs
             | otherwise = once xs

But as it is my code is doing the exact opposite, is returning me the repeated elements, and when I try to invert the return of the guards it just returns the complete list without the repeated elements, I'm really out of ideas on how to make it return what I want, only the unique elements that apear once in the list.

Upvotes: 3

Views: 454

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477533

There are basically three possible cases:

  1. the list is empty, so then we return an empty list;
  2. the list is not empty, and the first item x is an element in the remaining list xs, then we skip that item and filter out all items in the tail when we recurse; and
  3. the list is not empty and the first item x does not appear in the rest of the list xs, in that case we yield x, and recurse on xs.

The function thus looks like:

once :: [Int] -> [Int]
once [] = []
once (x:xs)
  | x `elem` xs = …
  | otherwise = …

I leave it as an exercise to fill in the parts. For the second case, you can make use of filter :: (a -> Bool) -> [a] -> [a].

Upvotes: 3

Related Questions