3 ms·
> Go's error handling is essentially the same as Error/Either/StatusOr (returning errors as values). Not really, it's very annoying to chain calls which can er
by tylerhou 8y ago
> Go's error handling is essentially the same as Error/Either/StatusOr (returning errors as values).
Not really, it's very annoying to chain calls which can error. Also, as another commenter mentioned, functions which can potentially fail should return sum types and not product types.
Compare:
do first <- computeFirst
second <- computeSecond
return $ f first second
and
first, err := computeFirst()
if err != nil {
return nil, err
}
second, err := computeSecond()
if err != nil {
return nil, err
}
return f(first, second), nil
Even without do-notation the Haskell is considerably shorter:
computeFirst >>= (\first ->
computeSecond >>= (\second ->
return $ f first second))
Agreed about exceptions, though; I dislike them as well.
- retzkek 8y ago> Even without do-notation the Haskell is considerably shorter This is a great example, not to your point, but to the methodology of Go. You give a verbose Go example, that I expect the vast majority of readers here could understand, even if they've never written a single line of Go, followed by a terse but syntax-heavy Haskell example that I expect relatively few could.
- erik_seaberg 8y agoThe Go version is 78% useless noise trying to hide f(computeFirst(), computeSecond()) which is what a maintainer needs to focus on. We know everything can fail, we don't need to be incessantly reminded of that. If completely inexperienced people can read idiomatic code, that means the idioms don't capture anything tricky that had to be learned the hard way. There's no payoff for getting better with the language.
- int_19h 8y agoThe last example is Haskell without the syntactic sugar. The first example is in Haskell how it's normally written, and it's far clearer than Go.
- zimpenfish 8y agoApologies, I know very little Haskell - does that example mean that `computeSecond` will always be called, even if `computeFirst` failed? If it does, it's not the same as the Go code which will not call `computeSecond` in that case (which might be a requirement - who knows?) I'm also assuming that `f first second` will return (an error monad?) if either of `first` or `second` are (an error monad?) - is that right?
- univalence 8y agoIt will not, because code inside a do-block is sequenced. The value `first` in the line `first <-computeFirst` is a non-error value. If computeFirst fails, the value does not exist (because computeFirst must return either an error or a non-error value), and so the whole computation fails.
- erik_seaberg 8y agoThis version of f can't fail, so "return" wraps its value in the same monad. Normally the "do" block would end by getting a monad from f, just as the Go version would normally let f return an error.
- tylerhou 8y agoIn the error monad above, computeSecond will not be called if computeFirst failed. But in other monads (which have the same syntax) computeSecond MAY be called depending on the rules of composition. return is a bit of a misnomer in Haskell -- it really means "wrap this value in the monad supplied by the context." So as other commenters have mentioned, f(...) cannot fail. Non-monadic Haskell functions never use return. If f could fail and you indeed wanted to propagate its error if it did fail, you could write the code as do first <- computeFirst second <- computeSecond f first second