[Haskell-cafe] MissingH bracketCD (aka bracketCWD) bug -- this is the infamous lazy io, right?

Thomas Hartman tphyahoo at gmail.com
Mon Mar 23 04:08:41 EDT 2009

I got bitten by  a bug (well, I call it bug) in bracketCD from
HSH/MissingH demonstrated by the following code

bracketCD is very useful for sysadminny one-offs, I use it all the
time, but..... I suspect that unless people are very careful, this
behavior will affect other users of bracketCD, in potentially very
subtle and tricky ways.

1) -- is there a more elegant way to deal with lazy io than the hack
below? (putStrLn the last character)
2) -- should MissingH function bracketCD be fixed, and if so how?

import System.FilePath.Find (find)
import System.Directory (getDirectoryContents, getCurrentDirectory,
import System.Path (bracketCWD) -- from MissingH

-- the fixed function, a more restrictive type than bracketCWD which
lets you do any io, not just showables
myBracketCWD :: Show a => FilePath -> IO a -> IO a
myBracketCWD fp action =
    do oldcwd <- getCurrentDirectory
	setCurrentDirectory fp
	a <- action
	putStrLn $ show . last . show $ a -- force evaluation
	setCurrentDirectory oldcwd
	return a

-- rather than listing "/", lists dir this module is in
tWrong = bracketCWD "/" $ return . take 2 =<< listCurrentWithFind

-- this lists filesystem root
tRight = myBracketCWD "/" $ return . take 2 =<< listCurrentWithFind

listCurrentWithFind = System.FilePath.Find.find (return True) (return True) "."

-- for some reason, bracketCWD does the right thing with get
tGetContents = myBracketCWD "/" $ return . take 2 =<< getDirectoryContents "."

Actual code for bracketCWD in MissingH:

-- this is from MissingH, seems there's a bug when attempt to wrap a
find command
bracketCWD :: FilePath -> IO a -> IO a
bracketCWD fp action =
    do oldcwd <- getCurrentDirectory
       setCurrentDirectory fp
       finally action (setCurrentDiurectory oldcwd)

More information about the Haskell-Cafe mailing list