Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top