Checking numbers for equality and different type signatures

Hello, I am reading a book to learn Haskell and I implemented some basic functions.

Today I wrote four different functions checking two numbers for equality. Three of them need numeric types, and one function can take every basic type.

Here they are:

equal_1 :: Integral a => (a -> (a -> Bool))

equal_1 x y = x == y

equal_2 :: Eq a => (a -> (a -> Bool))

equal_2 x y = x == y

equal_3 :: (Int -> (Int -> Bool))

equal_3 x y = x == y

And one functions which is wrong (tested with ghci):
equal_4 :: Num a => (a -> (a -> Bool))

equal_4 x y = x == y

Why is equal_4 wrong? There I use a class constraint. In equal_1 and equal_2 I use class constraints too and it works. The first function is limited to Integral types, the second function can take each basic type and function 3 is limited to Int.
And which type signature is the most useful? Does it depend on certain circumstances?
And should I use the class Eq in a type signature?


equal_4 :: x y = x == y has a :: that you need to remove, because this is the definition of the function, not the type signature.

I did not mean to write that. I meant equal_4 :: x y = x == y.

Isn’t that the same as before? Remove the ::, because this is the function definition not the type signature, and then it should work.

I think the fourth function is wrong because the Num constraint does not imply the Eq constraint which defines the == operator. In contrast, the Integral constraint does imply Eq via Integral <- Real <- Ord <- Eq.

I am not sure if this exercise is of didactic value, because even advanced Haskellers don’t know the hierarchy of numeric type classes by heart. (I had to look that up).

EDIT: To answer your other questions: There is no need to redefine ==, so none of these functions are “useful”. However, if you want to test two values for equality, you would always use the Eq constraint, and not any other such as Integral or Ord (e.g., one can also test strings for equality).