So this question is about Monads more generally (in particuar for Fay), but my example uses the IO monad.
I have a function where the input is a list of strings and I would like to print each string one by one. So here was my idea:
funct :: [String] -> ?
funct strs = do
map putStrLn strs
But doesn't work because it returns a type [IO ()]. So my question is, how would I map over a list, and treat it as if I'm performing the function line by line, in typical do-notation, iterative style (like below)?
funct :: [String] -> IO ()
funct strs = do
putStrLn (strs !! 0)
putStrLn (strs !! 1)
...
Most of the standard library list functions have monadic versions that end with M
:
map :: (a -> b) -> [a] -> [b]
mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
replicate :: Int -> a -> [a]
replicateM :: (Monad m) => Int -> m a -> m [a]
etc. Sometimes they are in Prelude
, sometimes they are in the Control.Monad
. I recommend using hoogle to find them.
Specifically for your case, i use mapM_ putStrLn
quite often.
Use sequence
sequence $ map putStrLn strings
sequence pulls the monad out of a list of monads
sequence :: Monad m => [m a] -> m [a]
thus converting (map putStrLn strings)::[IO a] to IO [a]. You might want to use the related sequence_ to drop the return value also.
You can also use forM_:: Monad m => [a] -> (a -> mb) -> m ()
(which often looks nicer, but has a bit of an imperative feel to me).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.