Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could not deduce (Eq a) from the context (...)

I'm new to Haskell. I wrote this code:

deleteDuplicates :: [a] -> [a]
deleteDuplicates [] = []
deleteDuplicates (x:xs)
        | x == (head xs)        = x : (deleteDuplicates (tail xs))
        | otherwise             = x : (head xs) : (deleteDuplicates (tail xs))

What does this error mean and why did it occur? Am I accidentally comparing two different types somehow?

set2.hs:10:3:
    Could not deduce (Eq a) from the context ()
      arising from a use of `==' at set2.hs:10:3-16
    Possible fix:
      add (Eq a) to the context of
        the type signature for `deleteDuplicates'
    In the expression: x == (head xs)
        In a stmt of a pattern guard for
                 the definition of `deleteDuplicates':
          x == (head xs)
    In the definition of `deleteDuplicates':
        deleteDuplicates (x : xs)
                           | x == (head xs) = x : (deleteDuplicates (tail xs))
                           | otherwise = x : (head xs) : (deleteDuplicates (tail xs))
like image 503
Pieter Avatar asked Nov 29 '22 16:11

Pieter


1 Answers

Your type signature is wrong:

deleteDuplicates :: [a] -> [a]

That says your function can work on lists of any type, a, but that isn't true! You later call:

x == (head xs)

So you must be able to compare your type for equality. Meaning the signature must be:

deleteDuplicates :: Eq a => [a] -> [a]

At times like this it's good to remove your explicit type signature, load the function in GHCi and discover what type the interpreter thinks it should have (via :t deleteDuplicates).

More Bugs

Additionally, your use of head there is a bad idea. head is a partial function and will fail when xs == []. I suggest you expand the pattern match:

deleteDuplicates (x1:x2:xs)
    | x1 == x2 = ...
    | otherwise = x1 : deleteDuplicates (x2:xs)

Also notice the fix to the otherwise case. You were skipping over x2, but what if x2 matched the next element in the list? Something like [1,2,2,3] would have discovered 1 /= 2 and then the recursion would have gotten the list [2,3] - oops!

like image 110
Thomas M. DuBuisson Avatar answered Dec 04 '22 02:12

Thomas M. DuBuisson