Here is a sample program from RWH book.  I'm wondering why the first works great but the second can't even compile? The only difference is the first one uses 2 tabs after where mainWith func = do whereas the second uses only 1. Not sure what difference does that mean? Why the second fails to compile? And also why do construct can be empty? 
Thanks a lot, Alex
-- Real World Haskell Sample Code Chapter 4:
-- http://book.realworldhaskell.org/read/functional-programming.html
import System.Environment (getArgs)
interactWith func input output = do
    s <- readFile input
    writeFile output (func s)
main = mainWith myFunction
    where mainWith func = do
            args <- getArgs
            case args of 
                [fin, fout] -> do
                    interactWith func fin fout
                _ -> putStrLn "error: exactly two arguments needed"
myFunction = id
-- The following code has a compilation error
-- % ghc --make interactWith.hs
-- [1 of 1] Compiling Main             ( interactWith.hs, interactWith.o )
-- 
-- interactWith.hs:8:26: Empty 'do' construct
import System.Environment (getArgs)
interactWith func input output = do
    s <- readFile input
    writeFile output (func s)
main = mainWith myFunction
    where mainWith func = do
        args <- getArgs
        case args of 
            [fin, fout] -> do
                interactWith func fin fout
            _ -> putStrLn "error: exactly two arguments needed"
myFunction = id