Sorry if I am being silly but I am a beginner in Haskell ans I am trying to make a print a List with putStrLn but i am not sure how to solve the next problem:
And I am trying to made a basic print List in Haskell with the code:
import System.IO
array = map show [1, 2, 3, 4]
main :: IO ()
main = do
map putStrLn array
but the compiler give me:
8 main.hs:7:3: error:
7 • Couldn't match expected type ‘IO ()’ with actual type ‘[IO ()]’
6 • In a stmt of a 'do' block: map putStrLn array
5 In the expression: do map putStrLn array
4 In an equation for ‘main’: main = do map putStrLn array
How I should fix it?
Haskell handles IO quite differently than other languages.
In a language like Java, System.Out.println(3)
is a statement which does not evaluate to a value, so you can't even write something like x = System.Out.println(3);
.
In a language like Lisp, (print 3)
evaluates to 3 and, in the process of evaluation, prints 3
. So saying something like (setq x (print 3))
will set the value of x
to 3
and also print 3
.
In Haskell, putStrLn "3"
represents the command to print 3
. Thus, saying x = putStrLn "3"
does absolutely nothing except assign x
to the command putStrLn "3"
.
Let's look at some types. We have
map :: (a -> b) -> [a] -> [b]
putStrLn :: String -> IO ()
Thus, we should have
map putStrLn :: [String] -> [IO ()]
map putStrLn array :: [IO ()]
In other words, map putStrLn array
is a list of "IO actions" which result in a value of type ()
(basically, this means that executing the actions results in no extra information).
However, in order to write
main :: IO ()
main = map putStrLn array
which is what
main :: IO ()
main = do map putStrLn array
translates to, we need map putStrLn
to be of type IO ()
, NOT of type [IO ()]
.
If you wish to execute an action for each element of a list, you can use the for_
function, which has type for_ :: (Foldable g, Applicative f) => g a -> (a -> f ()) -> f ()
. IO
is Applicative
and []
is Foldable
, so in particular for_ :: [String] -> (String -> IO ()) -> IO ()
is one type that for_
can take. The code looks like
import Data.Foldable (for_)
array :: [String]
array = map show [1, 2, 3, 4]
main :: IO ()
main = for_ array putStrLn
This would be equivalent in an imperative language to
for each x in array do {
putStrLn x;
}