Its very common where I come across some list of elements xs
and want to do something to do something with every Nth element. The simplest example would be the Sieve or Erastothenes, where you want to "knock out" every multiple of a given prime. The two ways I could do this would be explicit recursion passing along a counter variable; or zipWith ($) (cycle (replicate (n-1) id ++ f))
. So which way is better/more elegant/more commonly used, or is there some library function like mapEveryN :: (a -> a) -> Int -> [a] -> [a]
that I haven't found?
As you and bheklilr mention, cycle
provides a nice way to accomplish this. You can take advantage of laziness a bit though:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith ($) (drop 1 . cycle . take n $ f : repeat id)
The use of zipWith
and cycle
seems more idiomatic (complex behavior composed from simpler behaviors) than a hand-written recursive function that combines both tasks.
Note: tail
here makes this function undefined for n = 0
so drop 1
is preferable.
There isn't a library function for this that I'm aware of.