Just read Rust's Try v2 proposal, and this example caught my attention.

fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
    Self: Sized,
    F: FnMut(B, Self::Item) -> R,
    R: Try<Output = B>,
{
    let mut accum = init;
    while let Some(x) = self.next() {
        accum = f(accum, x)?;
    }
    try { accum }
}

Notice how try { accum } is generic w.r.t. the return type. This looks pretty monadic and, unsurprisingly, monadic operations can be translated to this Rust representation mechanically.

HaskellRust
return xtry { x }
m >>= ftry { f(m?)? }

We can translate the three monad laws into Rust code:

NameHaskell leftHaskell rightRust leftRust right
Left identityreturn a >>= hh atry{h(try{a?}?)?}h(a)
Right identitym >>= returnmtry{try{m?}?}m
Associativity(m >>= g) >>= hm >>= (\x -> g x >>= h)try{h(try{g(m?)?}?)?}try{E(m?)?}

where E stands for |x|try{h(g(x)?)?}. (I can't put it in the table because it confuses Markdown, ugh.)

Can we prove them in Rust? Right identity is a direct consequence. Quoting the RFC,

<T as Try>::from_output(x).branch() ⇒ ControlFlow::Continue(x) (aka try { x }? ⇒ x)

Associativity is also obvious. Don't know the proof of left identity yet, because you can't simply unwrap try{x?}: h(a?) is distinctly not h(a).