Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> The first thing to note is that there is no indication that foo or bar can fail

I think this is a part of the point: we are able to simply write direct style, and not worry at all about the effectual context.

> how do you find the code that will run when they do fail

AFAIU, this is also the point: you are able to abstract away from any particular implementation of how the effects are handled. The code that will when they fail is determined later, whenever you decide how you want to run it. Just as, in `f : g:(A -> B) -> t(A) -> B` there is no way to find "the" code that will run when `g` is executed, because we are abstracting over any particular implementation of `g`.



In languages like JavaScript, function calls that can throw are completely indistinguishable. In Go, calling a function that can fail is explicit and takes three lines of boilerplate, if you just want to propagate the error. That seems like too much. Rust has the ‘?’ operator, which is one character of boilerplate.

Though it does add noise, one character of boilerplate to indicate a function call that uses effects seems like the right amount? Functions that use lots of effects will likely have this character on every function call, but that seems like a good indicator that it’s tricky code.


Rust and Go errors are not really effectful in the "side effect" sense, they're just an ordinary return value of a function. There's really no difference between returning a result and any other enum. Otoh, panics are effectful, and that's the kind of thing you'd want to capture in an effect system.


Sure, but in a language with an effect system, it seems like effects would be used for errors, so it seems worth comparing error-handling techniques.

Go uses a single base type (interface) for “expected” errors and panics for errors that aren’t normally caught. I suppose those would be two different effects? For the “expected” errors, some kind of annotation on the function call seems useful.


The way I see it, effects would be implemented/assigned to the function where the error gets logged for instance. But as long as the error value remains local, a function can still be pure all else being equal.

This is not the case with exception looking code (aka panics) since it escapes normal control flow and I guess makes an error "punch" through stacks as they are unwinded.

A bit like being thrown toward global state. So if we consider panics as side effectful operations, we would have to change go to explicitly declare panics as side effects with a known function signature.

I guess one would want the list of side effects to be part of a function signature for full visibility. I wonder how that would influence backward compatibility.


It looks like exceptions (write the happy path in direct style, etc), but with exceptions, there is a `catch`. You can look for it and see the alternate path.

What might be a good way to find / navigate to the effectual context quickly? Should we just expect an IDE / LSP color it differently, or something?


There's a `catch` with effects as well, though, the effect handler. And it works very similarly to `catch` in that it's not local to the function, but happens somewhere in the calling code. So if you're looking at a function and you want to know how that function's exceptions get handled, you need to look at the calling code.


This is the case anytime errors are propagated to callers instead of handled locally, which is probably most cases.


Just to clarify because the grammar is a bit ambiguous in your comment: which case do you see as the common case? I suspect in most cases, people don't handle errors where they are thrown, but rather a couple of layers up from that point.


> I suspect in most cases, people don't handle errors where they are thrown, but rather a couple of layers up from that

Agreed, that's the point I was trying to make.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: