Reputation: 41919
All About Monads explains sequence_
:
The
sequence_
function (notice the underscore) has the same behavior assequence
but does not return a list of results. It is useful when only the side-effects of the monadic computations are important.
Then, looking at TestSequence.hs
:
import Control.Monad
f :: String -> IO ()
f x = print x
run :: [String] -> IO ()
run xs = sequence_ . map f $ xs
I can run it:
λ: run ["foo", "bar"]
"foo"
"bar"
Is sequence_
calling unsafePerformIO
on each IO ()
to get the result, i.e. the ()
?
And, is sequence_
discouraged? Or is it, for the IO Monad
, simply used "at the end of the world" to run a list of IO
actions?
Upvotes: 4
Views: 2563
Reputation: 153102
No, it is not calling unsafePerformIO
on each IO ()
action. In fact, its type is not even specific to IO
:
sequence_ :: (Monad m, Foldable t) => t (m a) -> m ()
In the old libraries, when it was specific to lists (rather than generic over all Foldable
s), it was implemented in the following perfectly readable way:
sequence_ [] = return ()
sequence_ (x:xs) = x >> sequence_ xs
It is absolutely not discouraged; sequence_
(and its big brother, mapM_
) are extremely useful, to the point that it is even one of my motivating examples for why Monad
s as an abstraction are useful.
Upvotes: 11