Search code examples
haskellmonadsio-monad

How do I use map over a list with do notation - ie avoid type `IO ()' with type `[IO ()]'?


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)
    ...

Solution

  • 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.