Sequential IO processing

Hi community, I am making my first steps in Haskell, reading Haskell wikibook and now stuck with one of the excercises, namely this one: Implement a function sequenceIO :: [IO a] -> IO [a]. Given a list of actions, this function runs each of the actions in order and returns all their results as a list. This is what I came with: ioOne :: Num a => IO a ioOne = do print guid return guid where guid = 2 ioTwo :: Num a => IO a ioTwo = do print guid return guid where guid = 3 sequenceIO :: Num a => [IO a] -> IO [a] sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x return result : sequenceIO xs First two functions are there because of the invocation that I've planned: sequenceIO [getGuid, getNextGuid]. However, this could not be compiled (GHC): Couldn't match expected type `[m a]' against inferred type `IO [a]' In the second argument of `(:)', namely `sequenceIO xs' In the expression: return result : sequenceIO xs In the expression: do result <- x return result : sequenceIO xs Fine, I thought, something wrong with the type of the 'sequenceIO xs' (becasue I am sure the type of 'result' is fine). So I wrote another program to check what happens to the result of IO action evaluation (namely, which type is assigned): bar :: Num a => IO a bar = do print guid return guid where guid = 2 foo = do result <- bar result This could not be compiled either: No instance for (Num (IO b)) arising from a use of `bar' at auxil.hs:8:19-21 Possible fix: add an instance declaration for (Num (IO b)) In a stmt of a 'do' expression: result <- bar In the expression: do result <- bar result In the definition of `foo': foo = do result <- bar result I am a newbie, so I am interpreting this like "Haskell could not construct Num from the result of invocation of bar, which is of type IO a". But why do I need this at all? When doing console I/O with 'result <- getLine', I do not need to reconstruct String from the result. What am I doing wrong? Where is the failure in reasoning? Thanks, Sergey

You did really well here. There's just one small detail that you missed, which is causing the problem:
sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x return result : sequenceIO xs
The problem is indeed here. The type of 'sequenceIO xs' is IO [a], but the
type of result is 'a'. You can't cons an 'a' onto an 'IO [a]'. Thus, what
you need is something like this:
sequenceIO [] = return []
sequenceIO (x : xs) = do result <- x xs'
<- sequenceIO xs -- to take the list out of the IO Monad
return result : xs'
On Thu, Feb 19, 2009 at 9:56 AM, Sergey V. Mikhanov
Hi community,
I am making my first steps in Haskell, reading Haskell wikibook and now stuck with one of the excercises, namely this one:
Implement a function sequenceIO :: [IO a] -> IO [a]. Given a list of actions, this function runs each of the actions in order and returns all their results as a list.
This is what I came with:
ioOne :: Num a => IO a
ioOne = do print guid return guid where guid = 2
ioTwo :: Num a => IO a
ioTwo = do print guid return guid where guid = 3
sequenceIO :: Num a => [IO a] -> IO [a]
sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x return result : sequenceIO xs
First two functions are there because of the invocation that I've planned: sequenceIO [getGuid, getNextGuid].
However, this could not be compiled (GHC):
Couldn't match expected type `[m a]' against inferred type `IO [a]' In the second argument of `(:)', namely `sequenceIO xs' In the expression: return result : sequenceIO xs In the expression: do result <- x return result : sequenceIO xs
Fine, I thought, something wrong with the type of the 'sequenceIO xs' (becasue I am sure the type of 'result' is fine). So I wrote another program to check what happens to the result of IO action evaluation (namely, which type is assigned):
bar :: Num a => IO a
bar = do print guid return guid where guid = 2
foo = do result <- bar result
This could not be compiled either:
No instance for (Num (IO b)) arising from a use of `bar' at auxil.hs:8:19-21 Possible fix: add an instance declaration for (Num (IO b)) In a stmt of a 'do' expression: result <- bar In the expression: do result <- bar result In the definition of `foo': foo = do result <- bar result
I am a newbie, so I am interpreting this like "Haskell could not construct Num from the result of invocation of bar, which is of type IO a". But why do I need this at all? When doing console I/O with 'result <- getLine', I do not need to reconstruct String from the result.
What am I doing wrong? Where is the failure in reasoning?
Thanks, Sergey _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

I tried this earlier as well: sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail This results in: Couldn't match expected type `IO [a]' against inferred type `[m a]' In the expression: return result : resultTail In the expression: do result <- x resultTail <- sequenceIO xs return result : resultTail In the definition of `sequenceIO': sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail
sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x return result : sequenceIO xs
The problem is indeed here. The type of 'sequenceIO xs' is IO [a], but the type of result is 'a'. You can't cons an 'a' onto an 'IO [a]'. Thus, what you need is something like this: sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x xs' <- sequenceIO xs -- to take the list out of the IO Monad return result : xs'

Sergey V. Mikhanov wrote:
I tried this earlier as well:
sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail
The last line should be return (result : resultTail) otherwise it will be parsed as (return result) : resultTail which is not what you want. Regards, apfelmus -- http://apfelmus.nfshost.com

Now works! Thank you very much -- a nice lesson learned for me. S.
I tried this earlier as well:
sequenceIO [] = return [] sequenceIO (x : xs) = do result <- x resultTail <- sequenceIO xs return result : resultTail
The last line should be
return (result : resultTail)
otherwise it will be parsed as
(return result) : resultTail
which is not what you want.
Regards, apfelmus

Just a small comment, it's great to see the beginners list being so useful! Thanks, everyone, beginners and 'otherwise'. -- Felipe.
participants (4)
-
Andrew Wagner
-
Felipe Lessa
-
Heinrich Apfelmus
-
Sergey V. Mikhanov