Adding a little more type info to your variables doesn't help you if you need to drastically change how a variable is accessed and mutated (memoized, retrieved from a service, persistence layer, etc.) while avoiding a running a giant find/replace across your entire project.
I feel like if you have a generic "context"-like notion then you can have a lot of this pass directly through. E.g. I recently changed where a Scala report gets most of its data, making it use an (async) web service rather than a database call, and I only really had to change the "top and bottom" - all the intermediate code handles any kind of context as a generic "F[_]", sometimes requiring particular typeclasses (Applicative, Comonad) depending on what it does with it.
Comments
I feel like if you have a generic "context"-like notion then you can have a lot of this pass directly through. E.g. I recently changed where a Scala report gets most of its data, making it use an (async) web service rather than a database call, and I only really had to change the "top and bottom" - all the intermediate code handles any kind of context as a generic "F[_]", sometimes requiring particular typeclasses (Applicative, Comonad) depending on what it does with it.