# Can mapEvery be implemented with foldr

For a function that displays a function for every nth item in the list:

``````mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith (\$) (drop 1 . cycle . take n \$ f : repeat id)
```

```

Is it possible to implement this using `foldr`

as usual `map`

?

EDIT: Changed "folder" to "foldr" in the header. Auto corrections ...

+3

source to share

Here's one solution

``````mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f as = foldr go (const []) as 1 where
go a as m
| m == n    = f a : as 1
| otherwise =   a : as (m+1)
```

```

This uses the " `foldl`

as `foldr`

" trick to pass state left to right through the list as you add. Essentially, if we read the type `foldr`

as `(a -> r -> r) -> r -> [a] -> r`

, then we instantiate `r`

as `Int -> [a]`

, where the integer passed in is the current number of elements that we passed without calling the function.

+6

source

Yes, he can:

``````mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f xs
= foldr (\y ys -> g y : ys) []
\$ zip [1..] xs
where
g (i, y) = if i `mod` n == 0 then f y else y
```

```

And since it's possible to implement in terms , you could get even more folds if you like. This even works on infinite lists: `zip`

`foldr`

``````> take 20 \$ mapEvery 5 (+1) \$ repeat 1
[1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2]
```

```

This is how it looks with even more `foldr`

and more investment `g`

:

``````mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery _ _ [] = []
mapEvery n f xs
= foldr (\(i, y) ys -> (if i `mod` n == 0 then f y else y) : ys) []
\$ foldr step (const []) [1..] xs
where
step _ _ [] = []
step x zipsfn (y:ys) = (x, y) : zipsfn ys
```

```

Now, would I recommend writing it this way? Absolutely not. This is about as confusing as you can get by continuing to write "readable" code. But it demonstrates that it is possible to use very powerful `foldr`

to implement relatively complex functions.

+1

source

All Articles