Typed error can be useful in certain cases, especially when accompanied with NoError type.
For example, in reactive programming, https://github.com/ReactiveCocoa/ReactiveSwift (typed error) allows us to create UI bindings only if Error is NoError, i.e.:
static func <~ <Source: BindingSource> (provider: Self, source: Source) -> Disposable?
where Source.Value == Value, Source.Error == NoError { ... }
// example
let alphaSignal: Signal<CGFloat, NoError> = ...
view.reactive.alpha <~ alphaSignalThis makes sense since UI binding only requires values to be sent, and not for errors.
Signal<T, NoError> clearly defines that this instance will never send error during its lifetime.
On the contrary, in https://github.com/ReactiveX/RxSwift (untyped error) for example, we need some runtime check (e.g. fatalError("don't send error")) before making a safe(?) UI binding, since Observable<T> doesn't guarantee it doesn't emit error.
That's why there are many attempts to ease the situation, e.g. Driver, PublishRelay, etc, but I don't think there could be any best compile-time solution for this problem without the help of type-system.
(There's ongoing discussion in ReactiveX/RxSwift#1470 for more detail)
Obviously, this can be said for Result<T, E> type as well.
Result<T, NoError> will express the success-only data, and this is also useful when there is a function that converts from Signal<T, NoError> to Result<T, NoError>, e.g. ReactiveSwift's SignalProducer.single().
Without Result<T, NoError>, the implementation of func single() -> Result<Value, Error>? will probably be splitted into 2 overloaded methods:
extension SignalProducer {
public func first() -> Result<Value>? { ... }
}
extension SignalProducer where Error == NoError {
// NOTE: We don't want to use `Result<Value>?` as return type
// because we already know it doesn't emit error.
public func first() -> Value? { ... }
}which will be :sadtroll:.
Slide (in Japanese): Result V.S. Result<T, E> // Speaker Deck
In the talk, I gave the above example code to illustrate:
Result<T>fails the abstraction of parametric polymorphism by having boring overloaded codeResult<Value, NoError>is isomorphic toValueNoErroris important for Non- Error-handling as well