Haskell: can't use "map putStrLn"?

21,770

Solution 1

The type of the main function should be IO t (where t is a type variable). The type of map putStrLn ls is [IO ()]. This why you are getting this error message. You can verify this yourself by running the following in ghci:

Prelude> :type map putStrLn ls
map putStrLn ls :: [IO ()]

One solution to the problem is using mapM, which is the "monadic" version of map. Or you can use mapM_ which is the same as mapM but does not collect the returned values from the function. Since you don't care about the return value of putStrLn, it's more appropriate to use mapM_ here. mapM_ has the following type:

mapM_ :: Monad m => (a -> m b) -> [a] -> m ()

Here is how to use it:

ls = [ "banana", "mango", "orange" ]
main = mapM_ putStrLn ls

Solution 2

Ayman's answer makes most sense for this situation. In general, if you have [m ()] and you want m (), then use sequence_, where m can be any monad including IO.

Share:
21,770
Jay
Author by

Jay

Updated on April 18, 2020

Comments

  • Jay
    Jay about 4 years

    I have a list of strings, and tried this:

    ls = [ "banana", "mango", "orange" ]
    
    main = do
           map PutStrLn list_of_strings
    

    That didn't work, and I can't understand why.

    ghc print-list.hs
    print-list.hs:3:0:
        Couldn't match expected type `IO t' against inferred type `[IO ()]'
        In the expression: main
        When checking the type of the function `main'
    

    Any hints? I suppose it has to do with map returning a list and not a value, but I didn't find an easy way to fix this.

    Right now the only way I know to print a list of strings is to write a function that will iterate the list, printing each element (print if the list is [a], but print and recurse if it's (a:b)). But it would be much simpler to just use map...

    Thanks!

  • Dietrich Epp
    Dietrich Epp almost 15 years
    Something that I wish I'd learned a lot sooner was that there's another mapM defined in Data.Traversable. This mapM works more data structures in addition to lists, such as maps and arrays.
  • Dave
    Dave almost 15 years
    I always thought that main should be of type IO (), never knew it could be forall t. IO t. That shows how you can learn something new each day :-)
  • Nawaz
    Nawaz almost 4 years
    I have an IO String and I want to map it to IO Int and print the Int. How do I do it in one line? Is that possible.