[Haskell-beginners] Evaluate behaviour

Elvio Rogelio Toccalino elviotoccalino at gmail.com
Wed Jul 7 23:56:06 EDT 2010


This is a common behaviour, Tom. I suggest you read about the
"semi-closed" state of Handles in the documentation for System.IO.

It's kind of Zen :D

Basically, you are reading lazily from a bytestring (1 chunk at a
time)... Although it may seem as your program read and processed the
whole bytestring, it didn't (it's lazy!). If you close the handle
before "using" the output (when you 'return' it from your main
function), you're shutting down the incoming data channel before a
single request for a chunk of the bytestring is made.

Check it out for yourself... don't hClose the handle, just leave it
be. (It's messy, I know, but experiment with it.)

2010/7/7, Tom Hobbs <tvhobbs at googlemail.com>:
> Hi guys,
>
> Thanks to everyone who helped me, I hit a milestone this evening and
> finally got the (small) bit of functionality I was working on, working!  A
> huge "thank you" to everyone who has taken the time to use very small
> words to explain things to me!  (I just need to sort out some nicer error
> handling now...)
>
> Just one more question... for today.
>
> Here's my code;
>
> import Network
> import System.IO
> (hGetLine,hClose,hPutStrLn,hSetBuffering,BufferMode(..),Handle,stdout)
> import Data.Bits
> import Data.Binary
> import Data.Binary.Put
> import Data.Binary.Get
> import qualified Data.ByteString.Lazy	as L
> import qualified Data.ByteString.UTF8	as UTF
> import Control.Monad
> import Control.Exception (evaluate)
>
> ping a t = do
> 	h <- connectTo a (PortNumber t)
> 	hSetBuffering h NoBuffering
> 	L.hPut h (encode (0xFAB10000 :: Word32))
> 	numStrings <- fmap (fromIntegral . runGet getWord64be) $ L.hGet h 8
> 	names <- (fmap (runGet $ readStrings numStrings) $ L.hGetContents h)
> 	evaluate names
> 	hClose h
> 	return names
>
> readStrings :: Int -> Get [String]
> readStrings n = replicateM n $ do
> 		len <- getWord32be
> 		name <- getByteString $ fromIntegral len
> 		return $ UTF.toString name
>
> This works in GHCi exactly as I want it to.  Note the call to "evaluate"
> in the ping function which allows me to close the handle before returning
> the IO [String].  This behaviour prints out the list of Strings as read
>  from the handle in GHCi, exactly what I wanted it to do.  Here's the
> strange part;
>
> If I remove the evalute line, and instead have;
>
> names <- evaluate (fmap (runGet $ readStrings numStrings) $ L.hGetContents
> h)
>
> GHCI claims that this is okay, but when I call ping I don't get any
> output.  I don't get any errors either, but I would expect to see the same
> list of Strings as before.
>
> Can anyone explain to me why that happpens?  I'm assuming it's something
> to do with the "<-" magic, but I don't know what.
>
> Thanks,
>
> Tom
>
>
> --
> Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>


More information about the Beginners mailing list