Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - Checking if all list elements are unique

I need to compare if all elements of a given list are unique. (For the record I am doing so for academic purposes.)

Here is what I have thus far:

allDifferent :: (Eq a) => [a] -> Bool
allDifferent list = case list of
    []      -> True
    (x:xs)  -> if x `elem` xs then False else allDifferent xs

Which works wonderfully!

Now, when I try to do it like this...

allDifferent2 :: (Eq a) => [a] -> Bool
allDifferent2 list
    | null list                                                     = True        
    | (head list) `elem` (tail list) || allDifferent2 (tail list)  = False
    | otherwise  

It just doesn't work as intended. I get the following output from GHCi:

*Main> allDifferent2 [1..4]
False
*Main> allDifferent2 [1..5]
True
*Main> allDifferent2 [1..6]
False
*Main> allDifferent2 [1..7]
True

i.e. For every list with an even amount of elements it outputs False and for an odd amount of elements, True.

What am I missing? Would anyone care to shine some light?

like image 541
Luis Dos Reis Avatar asked Jun 24 '15 20:06

Luis Dos Reis


People also ask

How do you check for duplicates in a list Haskell?

if it is just about knowing if the list contains duplicates you can use the nub function in Data. List like so: hasDup l = nub l == l (nub removes all duplicates... so this will be true only if there are no duplicates in the list.)

How do you check if an element is in a list Haskell?

elem :: element -> list -> Bool. Use elem if you want to check whether a given element exists within a list.

What does NS mean in Haskell?

The sequence (n:ns) is a shorthand for head - tail. Quite literally, the first value, the head, is called n and the remained are the other, potentially plural, n s, which is why it is called ns . Haskell has pattern matching.


1 Answers

An alternative exploiting notElem:

allDifferent :: (Eq a) => [a] -> Bool
allDifferent list = case list of
    []      -> True
    (x:xs)  -> x `notElem` xs && allDifferent xs

Minor variant, using pattern matching directly in the equations:

allDifferent :: (Eq a) => [a] -> Bool
allDifferent []     = True
allDifferent (x:xs) = x `notElem` xs && allDifferent xs

I tend to stay away from partial functions like head,tail, so the variants based on guards look worse to me.

like image 90
chi Avatar answered Oct 13 '22 01:10

chi