Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift Poem: Why I prefer typed error (for https://github.com/apple/swift-evolution/pull/757)

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 <~ alphaSignal

This 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 https://github.com/ReactiveX/RxSwift/pull/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:.

@inamiy

This comment has been minimized.

Copy link
Owner Author

@inamiy inamiy commented Nov 22, 2017

Slide (in Japanese): Result V.S. Result<T, E> // Speaker Deck

In the talk, I gave the above example code to illustrate:

  • How Result<T> fails the abstraction of parametric polymorphism by having boring overloaded code
  • Result<Value, NoError> is isomorphic to Value
  • How NoError is important for Non- Error-handling as well
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment