Monadic error-handing a win-win way of doing things.
People who dislike Go complain about being forced to check for error conditions too often (likewise with Java's checked exceptions.)
Using 'Either', you're not forced into checking; you can check, or you can let the caller handle it.
People who dislike Java's unchecked Exceptions complain that there's no way of knowing what will be thrown, or when. Using 'Either', this is made explicit.
> What about when validate fails? The error is returned to the caller, which is maybe suitable. What about when update-db fails? Should there be a retry? Try another service? Requeue? Tell the user? What about if the send-email fails?
The point is - you don't know! So your approach needs to be well-suited to not knowing, which Either is.
In my current Java codebase at work, there are different ways of 'handling' errors which have built up over the years. A call to a missing 'Limit getUserLimit(User)' might:
* throw a NotFound exception
* return null
* return a default
And you can't tell without diving in and reading the code. If it had been written with Either instead:
* the caller could trust it instead, rather than reading all the code that it calls
* easily convert it to another failure condition - the Either implementation in your language will have built-ins for 'orElse(null)', or 'orElseThrow(...)'
> Should there be a retry?
Either is an expression, which lends itself well to abstraction. This means you can likely write code to retry Eithers in general, as opposed to writing retry code for specifically inside your DbUpdater.