Hi,
In the first example the traceShows are only called as a side effect of evaluating the IO expression (traceShow "Bla" $ do traceShow "Bloe" runit) which happens only once (runit is a top-level binding). I assume that for the second example GHC lifts (traceShow "Num" print 2) out of the do block and similarly evaluates it only once.
The traceShow "Bloe" is not lifted out of there because it's under a lambda. E.g. if you do this instead:
runit :: IO ()
runit = traceShow "Bla" $ do
traceShow "Num" (print 2)
traceShow "Bloe" runit
You get
"Bla"
"Num"
2
"Bloe"
2
2
2
2
...
Jacco