[Haskell-cafe] IO and lazyness.

Daniel McAllansmith dm.maillists at gmail.com
Tue Mar 6 18:25:11 EST 2007

On Wednesday 07 March 2007 10:56, D.V. wrote:
> > The problem is that hGetContents only reads the contents of the file on
> > demand and, without the 'return $!' you don't demand the value until
> > somewhere outside of rechf.  By this point the hClose has happened and
> > hGetContents has no access to the file => no lines => no result.
> I must be really dumb but I don't get why 'at this point the hClose
> has happened'

Not at all.  Mixing laziness and unsafe IO can be tricksie little devils.  A 
bit like vinegar and baking soda, or, perhaps more accurately, nitric acid 
and a bale of cotton.

My general advice would be to stay away from hGetContents (which is unsafe) 
and just use explicit mechanisms, at least until your more familiar with 

> It seemed to me that when I typed at ghci's prompt    rechf "xxxx"  it
> tries to evaluate it.

As an aside ghci is actually executing something like 
putStrLn . show $ rechf "xxxx"
as a convenience for you.  It's demanding the value of rechf "xxxx" so that it 
can print it out.

> that makes it perform the IO action of opening the file, then
> performing the IO action of evaluating ( since I need the result )
> rechf2 "xxxx" and *lastly* performing the IO action of closing the
> file.

Your program actually says:
1) open file handle
2) create a String that will be read _on demand_ from file handle
3) close file handle
4) print the value which is computed from the String

Step 2 doesn't read anything from the file because it is lazy.
Step 4 the putStrLn that ghci added for you needs the String, which needs to 
read from the file, but it's too late.

When you insert the print that you originally had commented out you're adding 
a step 2.5 which needs value of the String which causes the file to be read.

As Matthew Brecknell shows it can be difficult to write a 'Step 2.5' that 
fixes the problem.

> So to me either I'm just too confused to understand or something
> doesn't work as it should be.

It's working as expected, the expectation being that the mixing of laziness 
and unsafe IO is likely to give you a headache unless you really know what 
you're doing.

The documentation of hGetContents could make this clearer, I think.

> I also tried using readFile ( again following Jeremy's suggestion )
> and it works :
> > rechf r = do
> >   f <- readFile "liste"
> >   return $ rech r $ lines f

Yeah, my advice is to use the explicit mechanisms, which aren't difficult, at 
least until you know enough not to blow your fingers off.


More information about the Haskell-Cafe mailing list