When you have
> let ls = [putChar 'x', putChar 'y']
you aren't executing the actions stored in that list, you're just constructing those actions, if that makes sense. You could have something like
printHelp :: IO ()
printHelp = putStrLn "You need to pass XYZ options to this program"
defined in a file. This doesn't immediately print out the message, but instead constructs an action that, once executed, prints that message to the console. Execution happens in one of two places: in the main
function and in GHCi.
It looks like you're using GHCi to execute code, which is awesome for exploring different functions, but is a bit different than executing code in a file. Whenever you evaluate an IO Something
action by itself in GHCi, it runs that IO action. Whenever you evaluate any other value in GHCi it inserts print
in front of that line. So when you do
> head ls
This has type IO ()
, and so the action putChar 'x'
is executed, resulting in x
being printed out to the console. When you do
> tail ls
This has type [IO ()]
, so GHCi tries to put a print
in front of it, making it equivalent to
> print (tail ls)
The print
function has type
print :: (Show a) => a -> IO ()
We've passed a list to print
here, and there is an instance of Show
for lists, but only when the elements of the list have an instance of Show
. So the compiler tries to see if IO ()
has an instance for Show
. Unfortunately, it does not, since IO
is a pretty complex type that represents that pretty much anything can happen. So the compiler shows an error that IO ()
doesn't have an instance for Show
.
If you want to instead run every action in a list in order, there is a function for that: Control.Monad.sequence
(or Control.Monad.sequence_
if you don't care about the result). This function actually works on all Monad
s, not just IO
:
> sequence_ (tail ls)
y> sequence_ ls
xy>
GHCi
knows to execute theIO
action - in the second case it get's a list ofIO
actions (which are not an instance ofShow
) - you can usesequence_ $ tail ls
to get something similar – Random Dev