Understanding Haskell Type Class use in Type Declarations - haskell

When we have a function that compares two things using the == comparison operator we add something like Eq a => a... to the type declaration; but this doesn't always seem to be the case.
For example, given the following function:
tail' xs = if length xs == 0
then []
else drop 1 xs
We make use of the == comparison operator, so I assumed the correct type decalaration would be:
tail':: (Eq a) => [a] -> [a]
However, running :t tail' tells me that the correct type decalartion is:
tail':: [a] -> [a]
Why is this the case? Why isn't Eq required in the type declaration?

Eq a => t says that a must be an instance of Eq in the type t. A type being an instance of Eq means that == is defined for that type. But in your definition of tail', you never use == on an a, not even by proxy. The actual use of == is in length xs == 0. The type of length xs (and 0) is Int, and Int is already an instance of Eq, so we already know it has == defined. Since you never use == on an a, you don't need an Eq a constraint.
If, however, you had said xs == [], which seems equivalent (both test whether a list is empty), you would have incurred an Eq a constraint. This is because == on [a] requires an Eq a constraint since it uses == on each list's entries to compare the lists. Since you can use length xs == 0 (or, even better, null xs), though, this added constraint is spurious and should be avoided.
(As an aside, drop 1 [] = [] so you don't even need your if, but that isn't relevant to the question asked.)

Related

Why does the type of local variables that are values affect the type of input variables in the type signature of a function?

Prelude> func f = [(show s, f == s) | s <- [0, 1..10]]
Prelude> :type func
func :: (Num a, Enum a, Show a, Eq a) => a -> [(String, Bool)]
I would expect f to just be an instance of Eq a but all the class constraints applied to s are also applied to f for some reason. Replacing s with any constant removes the relevant type constraint for f, and replacing s in the equality removes all class constraints except Eq a for f.
Can someone explain to me why does the type of local variables that are values affect the type of input variables that are values?
Eq doesn't exist in a vacuum. To compare two things for equality, you have to have two things. And, crucially, those two things have to be of the same type. In Haskell, 0 == "A" isn't just false; it's a type error. It literally doesn't make sense.
f == s
When the compiler sees this, even if it knows nothing else about the types of f and s, it knows what (==) is. (==) is a function with the following signature.
(==) :: Eq a => a -> a -> Bool
Both arguments are of the same type. So now and forevermore, for the rest of type-checking this expression, we must have f and s of the same type. Anything required of s is also required of f. And s takes values from [0, 1..10]. Your type constraints come as follows
Num is required since s takes values from a list of literal integers.
Enum is required by the [..] list enumeration syntax.
Show is required by show s.
Eq is required by the f == s equality expression.
Now, if we replace s with a constant, we get something like
func f = [(show s, f == 0) | s <- [0, 1..10]]
Now f is being compared with 0. It has no relation to s. f requires Eq (for (==)) and Num (since we're comparing against zero, a number). s, on the other hand, requires Enum, Num, Eq, and Show. In the abstract, this should actually be a type error, since we've given no indication as to which type s should be and there aren't enough clues to figure it out. But type defaulting kicks in and we'll get Integer out of it.

Haskell Programming Assignment, "Couldn't match expected type ‘Int’ with actual type ‘[a0] -> Int’ "and a few more Errors

The assignment I have: A function numOccurences that takes a value and a list, returning the number of times that value appears in the list. I am learning haskell and am getting frustrated, this is my code for this:
numOccurences:: b -> [a] -> Int
numOccurences n [ls]
|([ls] !! n==True) = (numOccurences(n (tail [ls])))+1
|otherwise = 0
The errors I am getting are as follows:
https://imgur.com/a/0lTBn
A few pointers:
First, in your type signature, using different type variables (i.e. b and a) creates the possibility that you could look for occurrences of a value of one type, in a list with another type, which in this case is not what you want. So instead of two type variables, you just want to use one.
Second, whatever the concrete type of your list is, whether it's [Char], [Int], etc., it needs to be equatable (i.e. it needs to derive the Eq typeclass), so it makes sense to use the class constraint (Eq a) => in your type signature.
Third, since we're traversing a list, let's use pattern matching to safely break off the first element of the list for comparison, and let's also add a base case (i.e. what we do with an empty list), since we're using recursion, and we only want the recursive pattern to match as long as there are elements in our list.
Lastly, try to avoid using indexing (i.e. !!), where you can avoid it, and use pattern matching instead, as it's safer and easier to reason about.
Here's how your modified function might look, based on the above pointers:
numOccurences :: (Eq a) => a -> [a] -> Int
numOccurences _ [] = 0
numOccurences n (x:xs)
| n == x = 1 + numOccurences n xs
| otherwise = numOccurences n xs

Haskell "No instance for (Eq a) arising from a use of `/='"

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!
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.

Haskell Confusing Type Classes / Polymorphism

So basically I've past learning this part way back a month ago, and I can do more complicated stuff but I still don't understand when I need "Ord" or "Eq" etc in my type definitions. When I look it up online its just so confusing to me for some reason.
E.g.
my_min :: Ord a => a -> a -> a
my_min n1 n2 = if n1<n2 then n1 else n2
Why does this need Ord? Can you give an example of when you need Eq as well (a very simple one)? I need a very clear, basic explanation of when you need to put these, what to look out for to do that, and how to avoid using these at all if possible.
Usually I just need something like "[Int] -> Int -> [Int]" so i know ok this function takes an integer list and an integer, and returns an integer list. But when it includes Eq or Ord I have no idea.
What about this Eq type in this example I found in my lecture notes about finding two lists is identical, how does it apply?
identical :: Eq a =>[a]->[a]->Bool
identical [] [] = True
identical [] _ = False
identical _ [] = False
identical (h1:t1) (h2:t2) =
if h1==h2
then (identical t1 t2)
else False
Thank you.
Ord implies that the thing can be ordered, which means that you can say a is smaller (or greater) than b. Using only Eq is like saying: I know that these two items are not the same, but I cannot say which one is greater or smaller. For example if you take a traffic light as a data type:
data TLight = Red | Yellow | Green deriving (Show, Eq)
instance Eq TLight where
Green == Green = True
Yellow == Yellow = True
Red == Red = True
_ == _ = False
Now we can say: Red is unequal to Yellow but we cannot say what is greater. This is the reason why you could not use TLight in your my_min. You cannot say which one is greater.
To your second question: "Is there any case where you have to use Eq and Ord?":
Ord implies Eq. This means that if a type can be ordered, you can also check it for equality.
You said you have mostly dealt with [Int] -> Int -> [Int] and you then knew it takes a list of integer and an integer and returns an integer. Now if you want to generalise your function you have to ask yourself: Do the possible types I want to use in my function need any special functionality? like if they have to be able to be ordered or equated.
Lets do a few examples: Say we want to write a function which takes a list of type a and an element of type a and returns the lisy with the element consed onto it. How would it's type signature look like? Lets start with simply this:
consfunc :: [a] -> a -> [a]
Do we need any more functionality? No! Our type a can be anything because we do not need it to be able to be ordered simple because that is mot what our function should do.
Now what if we want to take a list and an element and check if the element is in the list already? The beginning type signature is:
elemfunc :: [a] -> a -> Bool
Now does our element have to be able to do something special? Yes it does, we have to be able to check if it is equal to any element in the list, which says that our type a has to be equatable, so our type signature looks like this:
elemfunc :: (Eq a) => [a] -> a -> Bool
Now what if we want to take a list and a element and insert it if it is smaller than the first element? Can you guess how the type signature would look like?
Lets begin with the standard again and ask ourselves: Do we need more than just knowing that the element and the list have to be of the same type: Yes, becuase our condition needs to perform a test that requires our type to be ordered, we have to include Ord in our type signature:
conditionalconsfunc :: (Ord a) => [a] -> a -> [a]
Edit:
Well you want to see if two lists are identical, so there are two things you have to look out for:
Your lists have to contain the same type and the things inside the list have to be equatable, hence the Eq.
If you are working with fixed types like Int, you never need class constraints. These only arise when working with polymorphic code.
You need Eq if you ever use the == or /= functions, or if you call any other functions that do. (I.e., if you call a function that has Eq in its type, then your type needs to have Eq as well.)
You need Ord if you ever use <, >, compare or similar functions. (Again, or if you call something that does.)
Note that you do not need Eq if you only do pattern matching. Thus, the following are different:
factorial 1 = 1
factorial n = n * factorial (n-1)
-- Only needs Num.
factorial n = if n == 1 then 1 else n * factorial (n-1)
-- Needs Num and Eq.
factorial n = if n < 2 then 1 else n * factorial (n-1)
-- Needs Num, Eq and Ord. (But Ord implies Eq automatically.)

Haskell type definition, => etc

I am learning Haskell using Learn You a Haskell. On page 54 is an
implementation of take like so:
take' :: (Num i, Ord i) => i -> [a] -> [a]
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
I understand all the code apart from the first line.
The :: part I understand as meaning this is a type definition?
(Num i, Ord i) is a tuple. The first element of the tuple has to be
numeric, fair enough. the second param has to be able to be ordered.
The parameter is the same - both are i. This means that the types
have to be the same?
Why is it not (Num i, Ord j)? Isn't the 2nd tuple element
referring to the list? Which could be of any type?
What does => signify?
i -> [a] -> [a] means first parameter is numeric? 2nd param is any
type list, 3rd param is any type list. So this is saying first param
numeric, 2nd param a list of any type and it returns a list of any
type. Well that is understandable I suppose.
The stuff before the => are constraints. (Num i, Ord i) isn't really a tuple in the usual sense. It specifies a requirement that type class instances exist for whatever specific type i you call the function with.
So what this type signature is actually saying is that the type of take' is i -> [a] -> [a], but with the additional restriction that i must have Num and Ord instances, which amounts to requiring that you can do some basic arithmetic (Num being short for "numeric" I suppose) and compare which value is larger (Ord meaning values of that type have an ordering defined, i.e. you can sort them or such).
In this particular case, the comparison n <= 0 is what uses Ord, while the subtraction and numeric literals use Num.
This is covered in chapter 3 of LYAH, and these specific type classes (among others) are mentioned in the Typeclasses 101 section.
(Num i, Ord i) is not meant to be a tuple. Read the type signature as: take' is a function of the type i -> [a] -> [a] where i has to be a type of the typeclasses Num and Ord.
You might want to read the chapter "Typeclasses 101" again.

Resources