Hacker News new | ask | show | jobs
by tialaramex 640 days ago
You can choose to work with Rust's Result in a monadic way, that's what methods like Result::and_then and Result::or_else and so on are for.

Because it's just another type you could also do whatever else you like, unlike with the Exceptions in typical languages which have them where too bad, we bolted the information to the control flow so now we're going on a journey.

If you want to bolt control flow to some information in Rust that's fine, feel free to define a function which returns ControlFlow::Break for success if that suits you, the try operator understands what you meant, early success is fine. Actually you can see this reflected in the larger language because break 'label value; exists in Rust unlike for example C++.

1 comments

What makes Monad interesting is that it is a trait that you have implemented, so you can work generically any monads. I thereby feel like saying manually calling these methods is "monadic" kind of misses the point of why a monad was interesting in the first place.

Haskell's error handling isn't you sitting around calling monad methods: you implement the Monad trait so you don't have to, and it then all gets hidden behind do notation, with the result that you get the same control flow that you'd get just using exceptions.

It thereby is just constantly strange to me that people talk about any of these languages as if they learned something from Haskell... Haskell clearly wanted things like state and exceptions and such, but wanted to do so on top of a lazy pure functional core language.

The trick they came up with is thereby to define this trait called Monad, which lets you program into the control flow all of these bespoke behaviors you get from the imperative languages: state, exceptions, scopes, asynchronicity, list comprehensions... you name it.

But the end result is not in any way "manual": the end code doesn't involve destructuring an Either every time you make a call, but it also doesn't involve calling methods to deal with the errors. The end result is, as best as they could implement, exception handling!

And like, in the same way that people can make mistakes with manual memory allocation, so we prefer scope allocation, people can also make mistakes with manual error propagation, and so you'd expect we would prefer exception unwinding: the monad enforces consistency.

In that light, the behavior of most languages with respect to many of these behaviors is to just have hardcoded every function to be in a standard set of stacked monads for basic things everyone takes for granted: exceptions are just hardcoded monadic error handling.

But Rust? That isn't monadic error handling: that's just manual error propagation. If we are going to call Rust's manual error management regime "monadic", we should also call C's manual resource management regime "monadic". If you are doing it manually, it isn't monadic.

And sure, calling the methods of the monad kind of makes it look a bit less manual, but that's like moving on from C and now saying that Go's manual-ish resource management (defer) is monadic. If you aren't forced to do it the standard/correct way, it isn't monadic.