I have a function:
mapAtOriginal :: (a -> a) -> [Int] -> [a] -> [a]
mapAtOriginal f is xs = helper 0 is xs
where
helper _ [] xs = xs
helper c (i:is) (x:xs)
| c < i = x : helper (c+1) (i:is) xs
| otherwise = f x : helper (c+1) is xs
It works like this:
mapAtOriginal (*2) [0,3] [1,2,3,4] -- == [2,2,3,8]
So I want to rewrite it but using a map
function. I understand that map
applies to every element of the list, however, I need it applied only for specific indices.
How can I do it?
map
doesn't know “where in the list” it is. So you first need to encode that information into the elements themselves. This can be done with zip [0..]
, which basically annotates each element with position at which it occurs.
Then, in the function you map
, you just need to pattern-match on the annotation-tuple, and use an if
to decide whether or not to apply the manipulator function to the other tuple element.
Note that the combination of zip
and map
is always equivalent to a single pass zipWith
, so that's what you should preferrably use.