4 ms·
Did you even read the article? For the points 1 and 4 F# has exceptions that are handled seamlessly with this technique using a simple function in the chain, as
by tigershark 10y ago
Did you even read the article? For the points 1 and 4 F# has exceptions that are handled seamlessly with this technique using a simple function in the chain, as clearly showed in the article.
For point 2 you are just using a different operator from the normal composition one.
I don't understand your point 3.
- cousin_it 10y agoI'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.
- gclaramunt 10y agoFor 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 Foo -> Result<Foo1,Error> Foo1 -> Result<Foo2,Error> Foo2 -> Result<Foo3,Error> And use bind to compose them easily. I think the confusing part is the word "exception" as it mixes concepts.