I want to duplicate the n-th elemnt of a list and my knowledge of haskell is very limited. I tried splitting the list in two parts, then getting the last element of the first part and just pasting it between those parts:
dupl n (x:xs) = (take n (x:xs)) ++ ( (x:xs) !! n) ++ (drop n (x:xs))
But I always get the error:
Prelude> :l f.hs
[1 of 1] Compiling Main ( f.hs, interpreted )
f.hs:5:39:
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `(:)', namely `x'
In the first argument of `(!!)', namely `(x : xs)'
In the first argument of `(++)', namely `((x : xs) !! n)'
Failed, modules loaded: none.
Could someone tell me what I am doing wrong?
list !! n returns a list element, not a list. ++ can only concatenate lists; you can't add a list element to a list with ++.
To put it more formally, !! has a type of:
(!!) :: [a] -> Int -> a
which means that it accepts a list of as and an Int, and returns an a. ++, on the other hand, has a type of:
(++) :: [a] -> [a] -> [a]
which means that it accepts two lists of as and returns a new list of as. So you can see that ++ accepts lists, but !! doesn't return lists, so you're not allowed to chain them together like that.
How do we fix this? You need to put the element list !! n into a list, in order to concatenate it to the other two lists without the type checker throwing a hissy fit.
This should do the trick:
dupl n l = (take n l) ++ [l !! n] ++ (drop n l)
Equivalently, add the chosen element to the right-hand list, and concatenate that to the other half of the original list:
dupl n l = (take n l) ++ ((l !! n):(drop n l))
Caveat lector: both of the above functions, unlike @Marimuthu's suggestion, will raise an exception if n is an out-of-bounds index. The exception comes from !!.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With