I have nothing against (or for) a Result class. I’d argue that a library like cats or any development team can, could, and should develop their own structures if the current ones don’t fit. Try/Success/Fail are a reasonable answer to Either. On the other hand, adding one or a few simple classes isn’t a huge deal.
A few things about Fail. If one is going to create an disciplined error framework, why not base it on one that exists? Throwable meets every need I’ve ever seen.
It does allow accumulating errors. All Throwable have an optional “cause.” They were intended to handle cascading errors from the first release of Java. Each throwable can fill its stack-trace. They can handle errors created by multiple and separate threads.
Throwable are designed to be specialized. IOException is the root of every (non-runtime) exception caused by I/O. Any and all libraries can create their own error definition structure. Because Throwable already supports cascading errors, a private library can always handle errors from other libraries.
With traits, one can add any kind of type graph one needs. Both Java and scala can match on any subclass of Throwable or trait/interface. It’s not a good idea to have a complicated error infrastructure. The current Throwable hierarchy allows anything that is needed. Including type parameters. If the error is caused by a single object, or a complex collection of objects, a library author can always add instance variables to the Throwable. Any type declaration can be used.
Throwables need not be thrown. That’s the whole purpose behind Try. It catches things that are throw outside to control of the current library and returns it without unwinding its context. It allows halting the computational chain, poisoning it, or even recovering it.
For implementation convenience, it would be nice if Option, Success, Fail, Nothing were all rolled up into one thing. From a modeling perspective, not so much so. I suspect the current problem is from version skew. If there was a AnyRef like trait that indicated the null set, they could all fall into the same type hierarchy. But they were all defined at different times, for different reasons, and its too late now. Without putting them all on the deprecated list at least.
If any library wants to do that, it certainly can. A NothingHere[T] trait, a SomethingHere[T] trait, an InvalidComputation[E<:Throwable] trait. The first two should be IterableOnce[T] to handle the same semantics as Option and Success. The later two would be used for pattern matching. It would even be possible to have a NothingHere[T] and InvalidComputation mix-in. I’m not sure that last one would be a good idea. Some mix of toOption, toSuccess, toFail may be in order for interface boundaries.
I’m indifferent to the change. Which probably means I don’t think it’s worth the time. If a unified framework for these concepts are created, Option, Try, Success, Fail should be deprecated. Probably never removed from the language, but to encourage people to use the new unified framework.