IMO, the main difficulty with adding monad-like abstractions to Rust actually lies elsewhere, in the fact that Rust doesn't really have function types -- or rather, it has too many of them. Roughly speaking, Rust does not have a function type constructor. Instead, every function you define in Rust gets its own special, unique type, which implements a function interface -- of which there are three, Fn, FnMut and FnOnce, to represent the different ownership states of the variables captured in a closure.
This means that monad-style interfaces involving higher-order functions and higher kinds will end up needing not just polymorphism over type constructors, but also constrained polymorphism over interfaces. This represents a much more substantial extension to Rust's type system than you might first expect.
The reason Rust does this is because if every definition gets its own type, then type inference can tell you very precisely which functions are called where, which makes inlining a lot more precise and effective. This is an important piece of how Rust turns (for example) iterator-heavy code into efficient loops -- there are actually many fewer indirect calls than it superficially looks like.
Personally, I think this was a design mistake, but it is also a choice that I would not revisit now. Once a system is in the wild, with users who depend on you, we are usually constrained to evolutionary development rather than radical redesigns.
[1] http://blog.sigfpe.com/2009/02/beyond-monads.html
This way you can encode current binding environment into state and state changing code and have operations that use existing type checking and inference facilities of current Haskell (or Agda, or something else) compiler to rule out violations.
[2] https://jpaykin.github.io/papers/pz_linearity_monad_2017.pdf
I keep saying that what is language feature in Rust, C#, C++, Java and some other currently hot programming languages is an ordinary library in Haskell.