I have many nits to pick with the details of this proposal, but I’ll start by saying I wholeheartedly support adding Result to the standard library.
One of the standard library’s goals is to provide “common currency” types—building block types which are needed frequently in many different domains and systems and often need to be passed across module boundaries. Result is one of those types. It first started to appear before we had native error handling, but it survived throws and it will probably survive async too. We should provide a standard, interoperable implementation for our users.
Now, on to the nits.
The names success, failure, Value, and Error
I think success and failure are great names because they ground Result's cases in specific semantics. The stronger our idea is of what a type is for, the better able we are to provide meaningful operations on it. Naming the cases success and failure helps keep our Result type from devolving into an Either type—and that's a good thing, because Either's cases are meaningless and it makes the type harder to use.
I think Value and Error are the right concepts for the generic parameter names—they should not be something like Success and Failure to match the cases—but
the fact that Error shadows a closely related standard library type is troubling. We should rename that generic parameter to ErrorType, and probably change its counterpart to ValueType to match.
Overall, good work in this area. 
Non-Swift.Error failures
To further ground Result in a specific semantic, I think we should guarantee that the failure case's associated value is a Swift.Error. Ideally, we would take Slava's suggestion and make Swift.Error existentials conform to Swift.Error, but if we can't do that, I think we should drop the second generic parameter entirely and make the associated value an Error existential.
The proposed design bends over backwards to try to support non-Swift.Error errors, locking many useful APIs behind conditional conformances. But the case for allowing non-Error errors is pretty thin. The example Result<(URLResponse, Data), (Error, URLResponse?)> type is a monstrosity that would be difficult for users to handle, would disable a lot of Result's API surface, and could be more gracefully expressed by a custom error type like:
struct URLSessionError: Error {
var underlying: Error
var response: URLResponse?
}
If we can promise that Error is always a Swift.Error, I think we can significantly simplify and improve the type, while also further distancing it from Either.
Typed errors
This proposal only touches on the elephant in the room: Do we want to support typed throws?
I think Result should match throws on this question; we want people to be able to move easily between the Result world and the throws world, and if one of them supports more type information than the other, that's going to cause a lot of stumbling.
I think we should decide now between two alternatives:
-
Result<Value> and no typed throws
-
Result<Value, Error> and eventual support for throws<Error>.
I don't think we need to rush throws<Error> into the language right away, but I think we should either commit to adding it by Swift 6, or we should drop the Error generic parameter from Result. We shouldn't leave this part of our error design hanging.
I don't have a particularly strong opinion about whether we should or shouldn't support typed errors; my only position is that we should make a firm decision and design our language accordingly.
The unwrapped() method
I think we want a method like this, but I don't like the name because it's the only place where we talk about a Result "wrapping" anything. I would call it something like value() or get() or check().
Note that, if .failure always contained a Swift.Error, this method would always be available. That's another reason to constrain or remove the Error generic parameter.
The value and error properties
r.value is exactly equivalent to try? r.unwrapped(), so I don't think we need it. r.error doesn't have an exact equivalent, but I'm not sure that it carries its weight. If we want it, maybe we should consider supporting a catch? feature instead; then you could write catch? r.unwrapped().
The isSuccess property
We do need a good way to convert a Result to a boolean for simple branching, and I think this is a good answer.
The various map functions
This functionality is central to graceful Result handling. That's why I want it to look very different from what we're considering here.
To start, I think map(_:) and mapError(_:) should take throwing closures. This would basically mean that they dip briefly into the try world and then immediately go back to using Results. For map(_:), there would be no difference if you didn't use throwing expressions; for mapError(_:), you would be able to "fix" a failure by returning a new value, or throw a replacement error. Basically, you get a lot of extra flexibility for almost nothing. They might look something like this:
public func map<NewValue>(
_ transform: (Value) throws<Error> -> NewValue
) -> Result<NewValue, Error>
public func mapError<NewError>(
_ transform: (Error) throws<NewError> -> Value
) -> Result<Value, NewError>
(Making this work properly with a generic Error parameter would require typed throws. I'm not sure if that means we would need to defer adding these methods until we have typed throws. Maybe we could use a runtime check for now?)
If we do that, we might then consider dropping the flatMap variants. After all, flatMap { expr } would be exactly equivalent to map { try expr.unwrapped() }.
Finally, we might consider renaming these away from map and mapError to something a little less functional-programming-y. For instance, we could call them continuing (for processing successes) and correcting (for processing failures). We've already changed some flatMap(_:) variants to compactMap(_:); maybe we should take a cue from that.
The Result.init(_: () throws -> Value) initializer
This is a very useful convenience. I considered suggesting it should be an autoclosure, but now that I've written the section on map functions, I actually think using a closure here too creates a nice symmetry.
The fold(onSuccess:onFailure:) method
This is...kind of weird? It's like a general form of all of the other operations, but I'm not sure when you'd use it in practice other than for implementing those. Keep it internal.
Missing conveniences
The biggest thing I wish this Result type included is conveniences for converting from the (Value?, Error?) tuples/parameters we so frequently see today. I can imagine two different ways we might do that:
public init(value: Value?, error: Error?) {
switch (value, error) {
case (_, let error?):
self = .failure(error)
case (let value?, nil):
self = .success(value)
case (nil, nil):
self = .failure(Foundation._nilObjCError)
}
}
public static func converting<Return>(
_ body: @escaping (Result) -> Return
) -> (Value?, Error?) -> Return {
return { value, error in body(Result(value: value, error: error)) }
}
We might or might not have both, and this might make more sense as part of Foundation.
There's a lot to think about (and argue about) with this proposal, but the bottom line is, I wish we'd had Result in the standard library years ago. I just want to make sure the language and standard library speak with one voice on error typing.