You... don't. You have to rely on compiler optimizations to get good performance.
Monads are more-or-less syntax sugar. They give you a structure that allows these optimizations more easily, and also make the code more readable sometimes.
But in your example, update returns a new copy of the state, and you map it over a list for each step. The compiler tries to optimize that into in-place mutation.
IMO, having to rely so much on optimization is one of the weak points of the language.