I've read the article and don't completely understand your comment.
For point 1, if you want to use the railway approach instead of exceptions, you must annotate all functions in the chain.
For point 2, I was talking about the runtime cost.
For point 3, Result<Result<Foo,A>,B> isn't the same type as Result<Result<Foo,B>,A>. People in the Haskell world acknowledge that it's a big problem ("monads don't compose"), hence all the research on monad transformers and extensible effects etc.
For point 4, if your function is the lowest in the call stack and decides to report an error using the railway approach, you don't get a stack trace.
For 1 and 4, is not for runtime exceptions (div by 0, out of memory, etc) that you need to bubble up to the top, is for "logic"/checked exceptions where you want to use code to deal with the failure case.
For 3, that totally defeats the purpose, the whole point is to have a single error type (it can capture the details of the error anyway) then you can have
For point 1, if you want to use the railway approach instead of exceptions, you must annotate all functions in the chain.
For point 2, I was talking about the runtime cost.
For point 3, Result<Result<Foo,A>,B> isn't the same type as Result<Result<Foo,B>,A>. People in the Haskell world acknowledge that it's a big problem ("monads don't compose"), hence all the research on monad transformers and extensible effects etc.
For point 4, if your function is the lowest in the call stack and decides to report an error using the railway approach, you don't get a stack trace.