
On Tue, Nov 22, 2011 at 11:03:51PM -0500, Avery Robinson wrote:
Hello,
I was reading this block of code from http://jasani.org/2008/02/18/command-line-haskell-and-error-handling-example...
main = do m <- hGetContents stdin nums <- mapM readM . lines $ m print (sum nums) `catch` (\e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))
readM :: (Monad m, Read a) => String -> m a readM s | [x] <- parse = return x | otherwise = fail $ "Failed to parse \"" ++ s ++ "\" as a number." where parse = [x | (x,_) <- reads s]
I don't understand how line 5 works. I thought that the do notation there would be the same as:
main = hGetContents stdin >>= \m -> mapM readM . lines $ m >>= \nums -> print (sum nums) >> `catch` (\e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e))
Some experimentation shows that in fact, the first argument of `catch` is the *entire* do-block. That is, it is the same as main = (do m <- hGetContents stdin nums <- mapM readM . lines $ m print (sum nums) ) `catch` (\e -> hPutStrLn stderr ("couldn't sum lines: " ++ show e)) However, I don't understand why. I would have thought it invalid. Perversely, indenting the `catch` by one more space results in a valid program with different behavior (since it only applies to the print). -Brent