This is a simple fold
foo :: [Integer] -> ([Integer], Int)
foo [] = ([], 0)
foo (x : xs) = let (rs, n) = foo xs
in (2 * x : rs, if x == 5 then n + 1 else n)
or expressed using foldr
foo' :: [Integer] -> ([Integer], Int)
foo' = foldr f ([], 0)
where
f x (rs, n) = (2 * x : rs, if x == 5 then n + 1 else n)
The accumulated value is a pair of both the operations.
Notes:
- Have a look at Beautiful folding. It shows a nice way how to make such computations composable.
You can use
State
for the same thing as well, by viewing each element as a stateful computation. This is a bit overkill, but certainly possible. In fact, any fold can be expressed as a sequence ofState
computations:import Control.Monad import Control.Monad.State -- I used a slightly non-standard signature for a left fold -- for simplicity. foldl' :: (b -> a -> a) -> a -> [b] -> a foldl' f z xs = execState (mapM_ (modify . f) xs) z
Function
mapM_
first maps each element ofxs
to a stateful computation bymodify . f :: b -> State a ()
. Then it combines a list of such computations into one of typeState a ()
(it discards the results of the monadic computations, just keeps the effects). Finally we run this stateful computation onz
.