Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Interpret (Eq a)

I need to create a function of two parameters, an Int and a [Int], that returns a new [Int] with all occurrences of the first parameter removed.

I can create the function easily enough, both with list comprehension and list recursion. However, I do it with these parameters:

deleteAll_list_comp :: Integer -> [Integer] -> [Integer]
deleteAll_list_rec :: (Integer -> Bool) -> [Integer] -> [Integer]

For my assignment, however, my required parameters are

deleteAll_list_comp :: (Eq a) => a -> [a] -> [a]
deleteAll_list_rec :: (Eq a) => a -> [a] -> [a]

I don't know how to read this syntax. As Google has told me, (Eq a) merely explains to Haskell that a is a type that is comparable. However, I don't understand the point of this as all Ints are naturally comparable. How do I go about interpreting and implementing the methods using these parameters? What I mean is, what exactly are the parameters to begin with?


@groovy @pelotom

Thanks, this makes it very clear. I understand now that really it is only asking for two parameters as opposed to three. However, I still am running into a problem with this code.

deleteAll_list_rec :: (Eq a) => a -> [a] -> [a]
delete_list_rec toDelete [] = []
delete_list_rec toDelete (a:as) =
        if(toDelete == a) then delete_list_rec toDelete as
        else a:(delete_list_rec toDelete as)

This gives me a "The type signature for deleteAll_list_rec lacks an accompanying binding" which makes no sense to me seeing as how I did bind the requirements properly, didn't I? From my small experience, (a:as) counts as a list while extracting the first element from it. Why does this generate an error but

deleteAll_list_comp :: (Eq a) => a -> [a] -> [a]
deleteAll_list_comp toDelete ls = [x | x <- ls, toDelete==x]

does not?


2/7/13 Update: For all those who might stumble upon this post in the future with the same question, I've found some good information about Haskell in general, and my question specifically, at this link : http://learnyouahaskell.com/types-and-typeclasses

"Interesting. We see a new thing here, the => symbol. Everything before the => symbol is >called a class constraint. We can read the previous type declaration like this: the >equality function takes any two values that are of the same type and returns a Bool. The >type of those two values must be a member of the Eq class (this was the class constraint).

The Eq typeclass provides an interface for testing for equality. Any type where it makes >sense to test for equality between two values of that type should be a member of the Eq >class. All standard Haskell types except for IO (the type for dealing with input and >output) and functions are a part of the Eq typeclass."

like image 495
Soulzityr Avatar asked Nov 30 '22 01:11

Soulzityr


2 Answers

One way to think of the parameters could be:

(Eq a) => a -> [a] -> [a]

(Eq a) =>   means any a's in the function parameters should be members of the 
            class Eq, which can be evaluated as equal or unequal.*

a -> [a]    means the function will have two parameters: (1) an element of
            type a, and (2) a list of elements of the same type a (we know that 
            type a in this case should be a member of class Eq, such as Num or 
            String).

-> [a]      means the function will return a list of elements of the same 
            type a; and the assignment states that this returned list should 
            exclude any elements that equal the first function parameter, 
            toDelete.

(* edited based on pelotom's comment)

like image 159
גלעד ברקן Avatar answered Dec 05 '22 04:12

גלעד ברקן


What you implemented (rather, what you think you implemented) is a function that works only on lists of Integers, what the assignment wants you to do is create one that works on lists of all types provided they are equality-comparable (so that your function will also work on lists of booleans or strings). You probably don't have to change a lot: Try removing the explicit type signatures from your code and ask ghci about the type that it would infer from your code (:l yourfile.hs and then :t deleteAll_list_comp). Unless you use arithmetic operations or similar things, you will most likely find that your functions already work for all Eq a.

As a simpler example that may explain the concept: Let's say we want to write a function isequal that checks for equality (slightly useless, but hey):

isequal :: Integer -> Integer -> Bool
isequal a b = (a == b)

This is a perfectly fine definition of isequal, but the type constraints that I have manually put on it are way stronger than they have to. In fact, in the absence of the manual type signature, ghci infers:

Prelude> :t isequal
isequal :: Eq a => a -> a -> Bool

which tells us that the function will work for all input types, as long as they are deriving Eq, which means nothing more than having a proper == relation defined on them.


There is still a problem with your _rec function though, since it should do the same thing as your _comp function, the type signatures should match.

like image 26
us2012 Avatar answered Dec 05 '22 02:12

us2012