Even Go's error handling clearly isn't unusable, as controversial as it is, and try! is pretty much just a more sugary version of it.
Also, we were well aware of monads when we designed the Rust error handling system and in particular why they do not work very well in languages that have rich, imperative control flow structures. try! is basically just monads for imperative languages. To see this, work through what happens if you try to add break/continue/return to Haskell's system.
There are ways to transform code to allow this to work (there has to be, since Haskell is Turing-complete), but it's not straightforward.
The Option monad already is a sort of early return. Inside of monadic combinators, you use the monad for control flow instead of those statements. Seems fine to me, though admittedly my Type Theory Wizardry isn't the strongest.
This is why I called try! monads for imperative languages: the early return that is expands to is the key to playing nice with imperative constructs like break and continue.
instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f = f x
fail _ = Nothing
and instance (Error e) => Monad (Either e) where
return x = Right x
Right x >>= f = f x
Left err >>= f = Left err
fail msg = Left (strMsg msg)
The end result is still a value of that type. You get the short-circuting behavior as soon as you hit Nothing/Left.I would be very interested in a blog post on this.
When the blog post says "you don't need to learn monads", it's being tongue-in-cheek. He's pointing out that whilst Rust errors are monadic, you don't need to learn monads to work with them.
To be fair to Haskell, it doesn't force you to learn what a monad is either (ha!), but often the full details of what a monad is are emphasized before teaching IO or error handling. Which works somewhat, but also gives monads their infamy.