1

I'm just starting to get into the world of functional programming in a class. As a part of an assignment, we have to write a function that determines if a list is a singleton or not (if the list has exactly 1 element inside of it)

I've written the function and it works perfectly fine:

singleton x = x /= [] && x == take 1 (x) 

If I call singleton [1] it returns true as expected. If I call singleton [] or singleton [1,2,3] it returns false as expected.

However, my professor wants us to properly document the code with (I'm not exactly sure what this is called, but it tell haskell what to expect as input and output from the function):

singleton :: [a] -> Bool

As far as I can tell, this should work, but as soon as I have this, the compiler says "No instance for (Eq a) arising from a use of '/='"

Could anyone point me in the right direction to get the code compiled with that (I really have no clue what it's called) bit of function declaration?

Thanks!

Hashmush
  • 1,973
  • 2
  • 11
  • 12
  • 1
    possible duplicate of [Haskell: No instance for (Eq a) arising from a use of \`=='](http://stackoverflow.com/questions/16154592/haskell-no-instance-for-eq-a-arising-from-a-use-of) – Mephy Feb 18 '15 at 04:29
  • 1
    I don't think it's the same, because in that other question the function actually *needs* the `Eq a`, while in this one it can be rewritten to avoid it. – Ørjan Johansen Feb 18 '15 at 04:33
  • @ØrjanJohansen I think it's the same. Your function needs it, too. When you check whether [a] == [a], that implies checking the equality of a. – piojo Feb 18 '15 at 04:40
  • @piojo No, it doesn't, because the check `[x] == [x]` isn't necessary. – Hashmush Feb 18 '15 at 04:42
  • @Hashmush I mis-paraphrased, I meant `x == {x[0]}` (if you'll forgive me translating it into pseudo-code syntax). @ØrjanJohansen I see what you're saying about the error--while we can evaluate the first half of that check without needing the element to be in Eq, Haskell's actual equality check will have that type constraint. The comparisons for checking `(equals :: [a] -> [a] -> Bool)` `[] == x` and `y == x` are not separate functions with separate signatures, so the latter needing Eq will mean the former needs it, too. In other words, different cases don't have different type signatures. – piojo Feb 18 '15 at 04:46
  • 2
    @piojo The point is that you can write the function in such a way that it gets the type `[a] -> Bool` and not `(Eq a) => [a] -> Bool`. – Hashmush Feb 18 '15 at 04:48
  • @Hashmush Oh, gotcha. But the OP's specific question was "wtf is this error", so I'm just explaining it. I'm sure he'll be able to change the algorithm if he tries. :) – piojo Feb 18 '15 at 04:54
  • 1
    By the way, the `[a] -> Bool` part is called a [type signature](https://wiki.haskell.org/Type_signature). – Lambda Fairy Feb 18 '15 at 05:25

1 Answers1

7

In your code:

singleton x = x /= [] && x == take 1 (x) 

you do an equality test, x == take 1 x. This does a comparison of all the elements in the list to see if they are equal, so your elements must be "comparable". That's what Eq a is all about. The following fixes your problem:

singleton :: (Eq a) => [a] -> Bool
singleton x = x /= [] && x == take 1 (x)

But that is probably not what you want, since then your types must be comparable. You should be able to check if a list is a singleton without comparing the elements. But that is an exercise for you. Hint: It involves pattern matching.

Hashmush
  • 1,973
  • 2
  • 11
  • 12