Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding `sequence_`

Tags:

haskell

monads

All About Monads explains sequence_:

The sequence_ function (notice the underscore) has the same behavior as sequence 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?

like image 536
Kevin Meredith Avatar asked Sep 17 '25 00:09

Kevin Meredith


1 Answers

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 Foldables), 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 Monads as an abstraction are useful.

like image 100
Daniel Wagner Avatar answered Sep 18 '25 19:09

Daniel Wagner