Couldn't match expected type error - haskell

As a beginner, I was working on item number 3 of the Haskell 99 problems. The first code snippet is my solution. However, I cannot add the type declaration of [a] -> Int -> a.
It produces an error: Couldn't match type 'a' with 'Int'
--My Solution
--elementAt :: [a] -> Int -> a
elementAt xs num = head . reverse $ takeWhile (<num+1) xs
Meanwhile, one of the solution in the problem 3 works perfectly with the same output.
elementAt' :: [a] -> Int -> a
elementAt' list i = list !! (i - 1)
I've used the :type in the GHCI for the elementAt without the declaration and it shows:
elementAt :: (Num c, Ord c) => [c] -> c -> c
What is the difference of the two functions?

takeWhile (<num+1) xs says that you want to take elements at the front of the list xs while the element (not the index!) is less than num + 1. Since you're comparing num (which is an Int) with the list elements, the compiler infers that the list elements have to be Int as well, which contradicts your type declaration.
Without the type declaration, GHC infers that xs's elements and num have to be the same type (since you compare list elements with num). This type has to have an Ord instance (for the comparison) as well as a Num instance (because of the addition).

The type of takeWhile (< num + 1) is [Int] -> [Int].
However the type of xs is [a].
Essentially you are trying to apply a predicate Int -> Bool to elements of type a.
If you want to filter based on the position in the list, you first need to augment the input list with the position of each element. You can do this fairly easily with zip:
zip xs [1..]
You can then drop elements based on the value of the second element of the resulting list.

Related

Why is the type for [tail, init, reverse], [[a] -> [a]]?

This question is in one of the Haskell textbook exercises, not so smart question.
Question: What are the types of the following values?
[tail, init, reverse]
Solution: [[a] -> [a]]
But why?
tail, init and reverse are functions defined on a generic list, [a]. You read [a] as "a list of any type abstracted as a", in particular, if a = Int, you get [Int] - list of integers.
Now, function that takes a list and outputs a list of the same type has signature [c] -> [c] or, if c = a, [a] -> [a]. The letter picked up does not matter as long as you have the same latter on both sides, because [a] -> [b] would mean that you take somehow a list of as and map it to a list of bs - which - in general - a different type. You could say that a = Int and b = String and therefore you'd have to map Int to String anyhow; also you could say that b = a an thus reduce to the [a] -> [a] case.
The last one: [tail, init, reverse] is obviously yet another list, where a = [b] -> [b]. So you got [ [b] -> [b] ] type or, equivalently, [ [a] -> [a] ] or [ [k] -> [k] ]. Again: particular letter does not matter as long as you stick to the chosen one.
The type of the following value, not "values". singular. List of three elements is a value. Or did you mean "each of the values in the given list"? then they all must have the same type. since a list has a type [t] for some t. which implies all its elements have that same type t, whatever that is. then since tail :: [a] -> [a], so must be the other two that appear in the same list.
On their own they could each refer to a different letter i.e. "type variable". but inside the same list, they all must be in agreement. thus the type of the list as a whole is [ [a] -> [a] ].

Couldn't match type ‘a’ with ‘Int’ in Haskell

place n x is meant to find the place of integer n in the list x, for example place 2 [1,2,3] will return 1:
place :: Int -> [a] -> Int
place n x = length $ takeWhile (/=n) x
But it gets the error Couldn't match type ‘a’ with ‘Int’
Why? takeWhile should return a list and its length is an integer, hence place should output an Int eventually.
The correct type signature for place is:
place :: Int -> [Int] -> Int
When you use [a] in place of [Int] you are saying that place will work on a list of any type. For instance, I could call it like this:
place 3 [True, False, False, True]
or call it with a list of Char:
place 4 "this is a test"
But neither of these can work because takeWhile will compare each element of the list against the Int n. This forces the list to be a list of Ints.
You are using (/=) :: Eq ty => ty -> ty -> Bool where that second ty ~ Int due to the type of n. If ty is Int then the type of the other argument of (/=) (x) must be Int too.
find the place of integer n in the list x
ah, but there are no integers in the list at all. The type is [a]. Only if the type were [Int] would it be possible to find an n in it.
Now, you might say “[Int] is a possible instantiation of [a], so it could still work in that case”. Well, it could – but only in that case, and therefore it would be stupid not to enforce a ~ Int in the type signature.
More reasonably, you might want to find any type of number which happens to be equal to the integer n. Well, you can do that:
place' :: (Num a, Eq a) => Int -> [a] -> Int
place' n = length . takeWhile (/= fromIntegral n)
Here, I first convert n to the type of number that's contained in the list, and then compare it with those numbers.

How to create a base case for a tuple in Haskell?

I have the following function:
encode_single :: (Eq a) => [a] -> (Int, a)
encode_single (x:xs) = (count xs + 1, x)
However, Haskell complained about needing a base case, but I don't know how to do this because of the generic a type.
Thanks!
First of all, what you received is only a warning, not an error. Haskell does not need the base case of the empty list, it just suggests it.
Partial functions are most often an anti-pattern in functional programming so it just points out something that may be wrong. You can avoid the warning in different ways.
The first one is to make your function safe: if it cannot always return a value it's return type shouldn't be (Int, a) but Maybe (Int, a), so you could do:
encode_single :: (Eq a) => [a] -> Maybe (Int, a)
encode_single [] = Nothing
encode_single (x:xs) = Just (count xs + 1, x)
Otherwise you'd have to return a meaningful value for the empty case (just returning undefined isn't better than not defining that case). It might be appropriate to do somethign like:
encode_single [] = (0, undefined)
However this assumes that any code that uses the result of encode_single will not evaluate the second element of the tuple if the first element is zero (note that if the list isn't empty the first element is always positive, so 0 can be used as a sentinel value).
This may or may not be the case. However one thing is sure: this is not compile-time safe so you may receive some run-time errors when calling such a function.
Simply enough: at the type you desire you cannot write a total function of that specification. You need to change the type.
You can either add a default a or indicate partiality using Maybe.
encode_single :: a -> [a] -> (Int, a)
encode_single :: [a] -> Maybe (Int, a)
if you cannot change the type signature, you can piggyback on head i.e.
encode_single :: [a] -> (Int, a)
encode_single a = (length a, head a)
obviously, empty list input is not handled properly.

No instance for (Integral [t0]) error in Haskell code

I'm getting an error:
No instance for (Integral [t0]) when I run this haskell code.
boomBangs xs = [(a,b,c) |a<-[1..xs],b<-[1..xs],c<-[1..xs], xs <- xs `div` 2]
Where am I going wrong?
The problem is that you're trying to divide a list. In particular, xs `div` 2 is the incorrect expression.
You can get this from the error message: it's complaining that [t0] does not behave like an integer (e.g. it isn't in the Integral class). [t0] is just a list of stuff--the t0, being in lowercase, is a type variable that represntes any type.
Since lists of stuff aren't numbers, we can't really know how to divide them.
You can see why you get this exact error message by looking at the type of div:
div :: Integral i => i -> i -> i
All this means is that given some type i in the Integral class, you can divide two of them together to get a third. Since lists of things are not part of the integral class, you can't divide them and so you get an error.
If div had a concrete type like div :: Int -> Int -> Int, you would get an error telling you that it can't match the expected type Int with the actual type [t0]. However, since the type actually contains a variable i, the error is a bit more complex: [t0] cannot be a valid type to use in place of i because it is not in the Integral class.
What you said was:
Give me a tuple of a, b, and c:
[ (a, b, c)
For each a, b, and c in the list of values from 1 to xs1:
| a <- [1..xs1]
, b <- [1..xs1]
, c <- [1..xs1]
For each xs2 in the quotient of xs1 and 2.
, xs2 <- xs1 `div` 2
]
If you compile with warnings enabled (-Wall) or turn them on in GHCi (:set -Wall) then you’ll get a warning that the xs in xs <- ... shadows the xs in boomBangs xs = ..., and also that it’s unused. Obviously this kind of warning can be very helpful, as it points right to your problem.
Since xs1 is the input to your function, you end up with a type like this:
(Integral [t]) => [t] -> [([t], [t], [t])]
Which is to say that the function takes a list (xs1) that can act as a number ((`div` 2)) and gives you back a list of tuples of such lists. Even though you’re trying to divide a list by a number, GHC allows it and infers a more general type because you could have defined an Integral instance for lists. It only discovers that you haven’t when you actually try to use the function on a concrete type. Writing down type signatures can help keep the compiler grounded and give you better error messages.
I can only guess you meant for boomBangs to have a type like:
Integral t => [t] -> [(t, t, t)]
Or just:
[Int] -> [(Int, Int, Int)]
In which case maybe you were thinking of something like this:
[ (a, b, c)
| x <- xs
, a <- [1..x `div` 2]
, b <- [1..x `div` 2]
, c <- [1..x `div` 2]
]

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