Refactoring a stateless program into one that uses state is a big pain. Making programs that use different amounts of state, or kinds of state, at different parts within the program, is also a big pain. Functional programming languages including ones where monads are regularly used are just bad at this. You get towers of state transformers, or a lot of boilerplate for converting between one kind of state to another, and boilerplate for entering and leaving different kinds of stateful situations. Or you can just have one big state monad that goes everywhere, in which case there's three kinds of things, which are functions that live purely in IO, those which are pure, and those which live in your state monad.
But then you realize that certain purely IO actions need to do some logging and then they can't live in the IO monad and you need to refactor logging out of everything else and put your logging monad inside your state monad (and put a bunch of new liftIO's all over the place), but wait, didn't you just want to add some logging statements to debug this thing, and now you're tearing apart the structure of the world.
So maybe we could come up with some abstraction for logically separate components of a program's state, and then create a type of action that uses descriptors telling what subset of a program's state components are used, or we could not do that and recognize that functional programming does not work just fine, and that pure functional languages are bad at working with state.