Reader/State monad/effect mimic Dynamic scoping.
Dynamic scoping basically works as a global reader monad (re Dynamic scoping is a better model for global variables). Introducing local bindings is similar to local—modifies the environment and runs next code inside of it.
One difference is that dynamic scoping introduces a new binding that can be modified while Reader binding is constant. This can be further implemented by State monad or using Atom/IORef.
Dynamic scoping works badly with laziness because the local binding can come out of scope. Reader is much better here because the binding value can be properly captured.