Reputation: 2506
I have the following code, which takes a list, checks if each element's value is higher than the avg
and, it that's the case, prints val - avg
. I have already implemented it with recursion, I would like to transform it in order to use map
function.
loop [] = return ()
loop (x:xs)
| x > average = print (x - average) >> loop xs
| otherwise = loop xs
Any suggestion?
Upvotes: 0
Views: 194
Reputation: 34398
Note that each step of loop
does two things at once: they (possibly) generate a printing action out of each element of the list and then combine that action with the remaining ones (using (>>)
). If you want to write loop
in terms of map
, you need to disentangle these two sub-steps. For instance, you can define a function...
printDiffIfAboveAvg :: Double -> IO ()
... and then apply it to all elements of the list with map printDiffIfAboveAvg
. That will give you a list of actions, of type [IO ()]
, which you will need to combine into a single overall action:
runAllActions :: [IO ()] -> IO ()
runAllActions
already exists in the base library, in a more general version called sequence_
:
sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
So you would have loop = sequence_ . map printDiffIfAboveAvg
. In fact, there is also another function in the base library...
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
... which performs exactly this combination of sequence_
and map
.
Upvotes: 7