Remix.run Logo
solomonb 2 days ago

> How can you do "Errors as values" at a large scale without do-notation / monads?

You don't need monads for this. You just need the ability to encode your error in some term like `Either e a` and ability to eliminate those terms. In Rust for example that is the `Result` type and you use pattern matching to eliminate those terms.

greener_grass 2 days ago | parent [-]

Then you end up with a pyramid of doom. Fine for small examples but it doesn't scale up easily.

Rust has special syntax (`?`) for this AFAICT.

solomonb 2 days ago | parent | next [-]

You still don't need monads for any of this. Monads give you an ad-hoc polymorphic way of doing monadic actions.

Short circuiting on `Either` is a specific case of this. You can define your own EitherBind in any language.

    eitherBind :: Either e a -> (a -> Either e b) -> Either e b
    eitherBind (Left e) _ = Left e
    eitherBind (Right a) f = f a
Now you can bind over Either to your heart's content without needing an encoding of Monads in your language.
kccqzy 2 days ago | parent | prev | next [-]

That's merely syntax sugar. Haskell doesn't even have this sugar and so in a monad you have to bind explicitly, and it's fine. It's not a pyramid of doom.

greener_grass 2 days ago | parent [-]

Haskell has do-notation which is a more general kind of this syntactic sugar

2 days ago | parent | next [-]
[deleted]
kccqzy 2 days ago | parent | prev [-]

Yeah that's what I said about bind.

Let's consider a language like C++ where it has none of those syntax sugars. The absl::StatusOr is a class with the idea that errors should be values. The standard library has std::expected since C++23. So where is your pyramid of doom?

dllthomas 2 days ago | parent | prev [-]

`?` and `let ... else` both partially address this, yeah.