[Haskell-cafe] Monads and Functions sequence and sequence_
Roman Cheplyaka
roma at ro-che.info
Sat Oct 30 09:07:06 EDT 2010
* Mark Spezzano <mark.spezzano at chariot.net.au> [2010-10-30 15:37:30+1030]
> Can somebody please explain exactly how the monad functions "sequence"
> and "sequence_" are meant to work?
The others in this thread have already explained how these functions
work, so I'll just give an example how they are used.
Consider the following task: to read 30 lines from standard input.
For one line you would use an action
getLine :: IO String
How to execute this 30 times? Haskell has a function
replicate :: Int -> a -> [a]
which takes a number and produces a list with that number of
identical elements.
So this is close to what we need:
replicate 30 getLine :: [IO String]
This is a list containing 30 'getLine' actions. But the list of
actions _is not_ an action itself. This is what sequence does -- it
transforms a list of actions into a single action which gathers the
results into one list. As its name suggests, it does sequencing of
actions.
sequence $ replicate 30 getLine :: IO [String]
Exactly what we need, an action producing a list of lines read.
Now, let's consider this code:
sequence [ putStrLn $ show i ++ " green bottles standing on the wall"
| i <- reverse [1..10] ] :: IO [()]
This action prints 10 lines and also returns us gathered results, i.e.
10 '()', one from each putStrLn (recall that putStrLn has type "String -> IO ()".
Most probably we don't care about those '()', but they still occupy
memory and introduce a space leak as explained here[1]. That's why a
version of sequence is introduced which ignores the results of actions
and simply returns (). It is called "sequence_".
sequence_ :: (Monad m) => [m a] -> m ()
As a side note, we can rewrite our last example without using list
comprehension in the following way:
let p i = putStrLn $ show i ++ " green bottles standing on the wall"
in sequence_ $ map p $ reverse [1..10]
The combinations of sequence and sequence_ with map are so common that
they have special names:
mapM = \f -> sequence . map f :: (Monad m) => (a -> m b) -> [a] -> m [b]
mapM_ = \f -> sequence_ . map f :: (Monad m) => (a -> m b) -> [a] -> m ()
[1] http://neilmitchell.blogspot.com/2008/12/mapm-mapm-and-monadic-statements.html
--
Roman I. Cheplyaka :: http://ro-che.info/
"Don't let school get in the way of your education." - Mark Twain
More information about the Haskell-Cafe
mailing list