Q:

In Haskell, why do I need to put a $ before my do block?

[This question is motivated by Chapter 9 in "Real World Haskell"]
Here's a simple function (cut down to essentials):
saferOpenFile path = handle (\_ -> return Nothing) $ do
      h <- openFile path ReadMode
      return (Just h)

Why do I need that $ ?
If the second argument to handle isn't a do block, I don't need it. The following works just fine:
handle (\_ -> putStrLn "Error calculating result") (print x)

When I tried removing the $ compilation failed. I can get it to work if I explicitly add parens, i.e.
saferOpenFile path = handle (\_ -> return Nothing)  (do
      h <- openFile path ReadMode
      return (Just h))

I can understand that, but I guess I'm expecting that when Haskell hits the do it should think "I'm starting a block", and we shouldn't have to explicitly put the $ there to break things up.
I also thought about pushing the do block to the next line, like this:
saferOpenFile path = handle (\_ -> return Nothing)  
  do
    h <- openFile path ReadMode
    return (Just h)

but that doesn't work without parens either. That confuses me, because the following works:
add a b = a + b

addSeven b = add 7
   b

I'm sure I'll just reach the point where I accept it as "that's just how you write idiomatic Haskell", but does anyone have any perspective to give? Thanks in advance.

A:

This is due to Haskell's order of operations.  Function application binds tightest, which can be a source of confusion.  For example:
add a b = a + b
x = add 1 add 2 3

Haskell interprets this as: the function add applied to 1, and the function add.  This is probably not what the programmer intended.  Haskell will complain about expecting a Num for the second argument, but getting a function instead.
There are two solutions:
1) The expression can be parenthesized:
x = add 1 (add 2 3)

Which Haskell will interpret as: the function add applied to 1, then the value of add 2 3.
But if the nesting gets too deep, this can get confusing, hence the second solution.
2) The $ operator:
x = add 1 $ add 2 3

$ is an operator that applies a function to its arguments.  Haskell reads this as: the function (add 1) applied to the value of add 2 3.  Remember that in Haskell, functions can be partially applied, so (add 1) is a perfectly valid function of one argument.
The $ operator can be used multiple times:
x = add 1 $ add 2 $ add 3 4

Which solution you pick will be determined by which you think is more readable in a particular context.

A:

This actually isn't quite specific to do-notation.  You also can't write things like print if x then "Yes" else "No" or print let x = 1+1 in x*x.
You can verify this from the grammar definition at the beginning of chapter 3 of the Haskell Report: a do expression or a conditional or a let expression is an lexp, but the argument of function application is an aexp, and an lexp is generally not valid as an aexp.
This doesn't tell you why that choice was made in the Report, of course.  If I had to guess, I might surmise that it's to extend the useful rule "function application binds tighter than anything else" to the binding between, say, do and its block.  But I don't know whether that was the original motivation.  (I find the rejected forms like print if x then ... hard to read, but that may just be because I'm used to reading code that Haskell accepts.)

A:

According to the Haskell 2010 report, do desugars like this:
do {e;stmts} = e >>= do {stmts}
do {p <- e; stmts} = let ok p = do {stmts}
                         ok _ = fail "..."
                     in e >>= ok

For the second case, it's the same to write it desugaring like this (and easier for demonstrative purposes):
do {p <- e; stmts} = e >>= (\p -> do stmts)
So suppose you write this:
-- to make these examples shorter
saferOpenFile = f
o = openFile

f p = handle (\_ -> return Nothing) do
    h <- o p ReadMode
    return (Just h)

It desugars to this:
f p = handle (\_ -> return Nothing) (o p ReadMode) >>= (\h -> return (Just h))

Which is the same as this:
f p = (handle (\_ -> return Nothing) (o p ReadMode)) >>= (\h -> return (Just h))

Even though you probably intended for it to mean this:
handle (\_ -> return Nothing) ((o p ReadMode) >>= (\h -> return (Just h)))

tl;dr - when do syntax is desugared, it does not parenthesize the entire statement like you would think it should (as of Haskell 2010).
This answer is only AFAIK and

may not be correct 
may be outdated someday if it is correct

Note: if you say to me "but the actual desugaring uses a 'let' statement that should group e >>= ok, right?", then I would answer the same as the tl;dr for do statements: it doesn't parenthesize/group like you think it does.

