
Hi guys, Thanks for all the previous help I'm having with serialization in Haskell, I couldn't have gotten as far as I have without the help from this group. Many thanks! Now I've put you in a good mood, maybe you can help me with my latest problem... :-) I have the following code which reads strings from a handle; import qualified Data.ByteString.Lazy.UTF8 as UTF readNames 0 _ = [] readNames n h = do length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4 name <- L.hGet h length (UTF.toString name) : readNames (n-1) h Where n is the number of names remaining to read and h is the handle to the stream that I'm reading from. It is my intention that this function would return a [String] of all the names. I'm sure further explainations probably aren't necessary, but just in case; - "length" becomes equal to some number (represented by four bytes) which describes the length of the string to read - "name" becomes the string I'm trying to read - Then I add that String to the list and go again But the problem I'm getting is this; Couldn't match expected type `[a]' against inferred type `IO b' In a stmt of a 'do' expression: length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4 In the expression: do { length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4; name <- L.hGet h length; (UTF.toString name) : readNames (n - 1) h } In the definition of `readNames': readNames n h = do { length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4; name <- L.hGet h length; (UTF.toString name) : readNames (n - 1) h } I (think I) understand what the message is saying, but not why it's occurring. I read the documentation as "UTF8.tostring" essentially rips the [Char] out of the ByteString and returns that, so where does the "IO b" come into it? Is it complaining because the reads from the handle are IO operations and it's expecting me to use the IO monad somewhere? What i want to be able to do is do the IO stuff inside the monad, but end up with a [String] which I can then use in a pure function. RWH and Learn You A Good Haskell all cover some stream reading, but their examples are to different from what I'm trying to do that I'm getting stuck. Any pointers are very gratefully accepted. Many thanks, Tom

It's the type signature of hGet that is your undoing. it returns IO
ByteString, and then you are trying to apply a pure function to that. You
need to lift the pure function into the IO monad.
On 1 July 2010 12:55, Tom Hobbs
Hi guys,
Thanks for all the previous help I'm having with serialization in Haskell, I couldn't have gotten as far as I have without the help from this group. Many thanks!
Now I've put you in a good mood, maybe you can help me with my latest problem... :-)
I have the following code which reads strings from a handle;
import qualified Data.ByteString.Lazy.UTF8 as UTF
readNames 0 _ = [] readNames n h = do length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4 name <- L.hGet h length (UTF.toString name) : readNames (n-1) h
Where n is the number of names remaining to read and h is the handle to the stream that I'm reading from. It is my intention that this function would return a [String] of all the names. I'm sure further explainations probably aren't necessary, but just in case;
- "length" becomes equal to some number (represented by four bytes) which describes the length of the string to read - "name" becomes the string I'm trying to read - Then I add that String to the list and go again
But the problem I'm getting is this;
Couldn't match expected type `[a]' against inferred type `IO b' In a stmt of a 'do' expression: length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4 In the expression: do { length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4; name <- L.hGet h length; (UTF.toString name) : readNames (n - 1) h }
In the definition of `readNames': readNames n h = do { length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4; name <- L.hGet h length; (UTF.toString name) : readNames (n - 1) h }
I (think I) understand what the message is saying, but not why it's occurring. I read the documentation as "UTF8.tostring" essentially rips the [Char] out of the ByteString and returns that, so where does the "IO b" come into it? Is it complaining because the reads from the handle are IO operations and it's expecting me to use the IO monad somewhere? What i want to be able to do is do the IO stuff inside the monad, but end up with a [String] which I can then use in a pure function.
RWH and Learn You A Good Haskell all cover some stream reading, but their examples are to different from what I'm trying to do that I'm getting stuck.
Any pointers are very gratefully accepted.
Many thanks,
Tom
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hi As Benjamin Edwards says you want to be in the IO monad as you are using a file handle Something like this - note the last two lines have changed a bit to accommodate the computation being in the IO monad rather than pure, if you have very large input data you might need to put this in tail recursive form. readNames :: Int -> Handle -> IO [String] readNames 0 _ = return [] -- add a return, to lift the answer into IO readNames n h = do length <- fmap (fromIntegral . runGet getWord32be) $ L.hGet h 4 name <- L.hGet h length rest <- readNames (n-1) h return ((UTF.toString name) : rest)
participants (3)
-
Benjamin Edwards
-
Stephen Tetley
-
Tom Hobbs