Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying putStr to each item of a list

I'm trying to print out a list of integers in this format

[1]
[2]
[3]

So my function takes a list of integers and returns an IO () like so:

import System.IO

printVector :: [Integer] -> IO ()
printVector (x:xs) = putStr("[" ++ show(x) ++ "]" ++ "\n") : printVector xs

But ghc gives me the error:

lin-test.hs:5:22:
Couldn't match expected type `IO ()' with actual type `[a0]'
In the expression:
  putStr ("[" ++ show (x) ++ "]" ++ "") : printVector xs
In an equation for `printVector':
    printVector (x : xs)
      = putStr ("[" ++ show (x) ++ "]" ++ "") : printVector xs
Failed, modules loaded: none.

Now it is my understanding that the function would run through the list, taking the first item 'x' first, and then with : printVector xs it would recursively call the rest of the list applying the same putStr function to each item in the list.

But I think my problem is where I do : printVector xs? Can anyone point out what i'm doing wrong here?

like image 205
Donna Avatar asked Mar 16 '13 14:03

Donna


1 Answers

You need to map over the list but, as these are IO actions, you also need to execute them (as map will return a list of IO action without executing them, see following example).

sequence $ map (putStrLn . show) [1,2,3,4]

There is a function doing that already, it's mapM. So the example can be simplify as :

mapM (putStrLn . show) [1,2,3,4]

Another thing you can do is using mapM_ which uses sequence_ instead and will ignore the result of executing the IO action to each of the elements. Therefore, the return type will be IO () instead of IO [()] (previous example).

mapM_ (putStrLn . show) [1,2,3,4]
like image 164
tomferon Avatar answered Oct 28 '22 05:10

tomferon