Something like this looks pretty good.
unique = fst . foldl' (\(a, b) c -> if (c `elem` b) then (a, b) else if (c `elem` a) then (delete ca, c:b) else (c:a, b)) ([],[])
The first element of the resulting fold tuple contains what you expect, a list containing a unique element. The second element of the tuple is the process memory, which is remembered if the element is already discarded or not.
About space performance.
Since your design issue is, the entire list item must go through at least once before the result can be displayed. And the internal algorithm should contain traces of the discarded value in addition to the good one, but the discarded value will be displayed only once. Then in the worst case, the required amount of memory is equal to the size of the entered list. These sound products, as you said, are expected.
About the performance of time.
Since the expected input is small and not sorted by default, trying to sort the list into an algorithm is useless, or it is useless to apply it earlier. In fact, statically we can almost say that the additional operation of placing an element in its ordered place (in the subcategory a and b tuple (a,b) ) will cost the same amount of time as to check whether this element is displayed in the list or not .
Below is a nicer and more explicit version of foldl 'one.
import Data.List (foldl', delete, elem) unique :: Eq a => [a] -> [a] unique = fst . foldl' algorithm ([], []) where algorithm (result0, memory0) current = if (current `elem` memory0) then (result0, memory0) else if (current`elem` result0) then (delete current result0, memory) else (result, memory0) where result = current : result0 memory = current : memory0
In the if ... then ... else ... nested command, the result list goes twice in the worst case, this can be avoided by using the following helper function.
unique' :: Eq a => [a] -> [a] unique' = fst . foldl' algorithm ([], []) where algorithm (result, memory) current = if (current `elem` memory) then (result, memory) else helper current result memory [] where helper current [] [] acc = ([current], []) helper current [] memory acc = (acc, memory) helper current (r:rs) memory acc | current == r = (acc ++ rs, current:memory) | otherwise = helper current rs memory (r:acc)
But the helper can be rewritten using fold as follows, which is definitely better.
helper current [] _ = ([current],[]) helper current memory result = foldl' (\(r, m) x -> if x==current then (r, current:m) else (current:r, m)) ([], memory) $ result