And don't say "monad transformer stacks" somehow solve this problem in an easier way.
I find the "oh you changed tiny piece of logic, you should totally have to refactor every line of code that follows it" very strange. It obviously sucks, there are far better ways to handle it and they are slowly making it into the language.
You get the performance benefits of non-blocking code.
The simplicity benefits of blocking code.
And (almost) none of the threading hell you get in imperative languages.
This is some documentation of the scheduler: http://blog.ezyang.com/2013/01/the-ghc-scheduler/
var a = await someBigFunc()
a <- someBigFunc()
a <- doFirstThing()
b, c <- doSecondThing(a)
doFinalThing(b + c)