Reputation: 145
So I'm learning haskell right now, and I'm having trouble understanding what I'm doing wrong for the following function that inserts an element x
at index k
in list l
1.insertElem x k l = take k l ++ (x : drop k l)
2.insertElem x k l = (take k l : x) ++ drop k l
Now, I know that the correct answer is number 1, but I don't understand why number 2 is wrong for the call insertElem 2 5 [0,0,0,0,0,0]
.
The error is "Cannot construct the infinite type: a ~ [a]. Expected type: [[a]], Actual type: [a]"
Upvotes: 1
Views: 70
Reputation: 20415
A recursive definition of insertElem
that illustrates the use of (:)
,
insertElem :: a -> Int -> [a] -> [a]
insertElem e 0 xs = e : xs
insertElem e k [] = [e] -- k > length xs
insertElem e k (x:xs) = x : insertElem e (k-1) xs
Here insertElem
delivers a list of a
to which we append either the current head of the list of else the actual element to be inserted.
The appending of an element of type a
to a list of a
uses (:)
. Note in the second case we append an element e
to an empty list, namely [e]
; this is equivalent to e : []
. In the last case we extract the head of the list also with (:)
.
Upvotes: 1
Reputation: 52270
Your problem is (as Silvio already told you) the use of :
but let's analyse the types to see where the error comes from and how you could see it yourself:
look at
(take k l : x) ++ drop k l
(++)
has type [a] -> [a] -> [a]
so both parts take k l : x
and drop k l
need to be lists of the same type.
looking at drop
you get Int -> [a] -> [a]
so you now know:
k
has type Int
l
has type [a]
[a]
take k l : x
too needs to have type [a]
now look at (:)
it has type a -> [a] -> [a]
so for it to work out you now need x
to have type [a]
and take k l
to have type a
.
take
has type Int -> [a] -> [a]
and we already know that l
has type [a]
so you get:
take k l
has type [a]
(:)
) take k l
to be of type a
So you need a
to be somehow at the same time to be [a]
that is what a ~ [a]
means and is what the error says.
Upvotes: 7
Reputation: 70267
The :
operation adds an element (the first argument) to a list (the second argument). Thus, it expects the first argument to be an element and the second to be a list, not the other way around. If you want to do it that way, you would do this:
insertElem x k l = take k l ++ [x] ++ drop k l
Upvotes: 4