Created
September 7, 2014 13:46
-
-
Save rnapier/b383d2542c9fabe913c9 to your computer and use it in GitHub Desktop.
Proof: flatMap<Result> and continueWith are the the same function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Claim: flatMap<Result> and continueWith are the the same function | |
// | |
// Begin with flatMap and its dependencies | |
// | |
func flatMap<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
return flatten(map(x, f)) | |
} | |
func map<T, U>(x: Result<T>, f: T -> U) -> Result<U> { | |
switch x { | |
case .Success(let box): return .Success(Box(f(box.unbox))) | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
func flatten<T>(x: Result<Result<T>>) -> Result<T> { | |
switch x { | |
case .Success(let box): | |
switch box.unbox { | |
case .Success(let nestedBox): return .Success(nestedBox) | |
case .Failure(let err): return .Failure(err) | |
} | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// Substitute map(x, transform) | |
// | |
func flatMap1<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
return flatten({ (x1: Result<T>, f1: T -> Result<U>) -> Result<Result<U>> in | |
switch x { | |
case .Success(let box): return .Success(Box(f1(box.unbox))) | |
case .Failure(let err): return .Failure(err) | |
} | |
}(x, f)) | |
} | |
// | |
// Substitute flatten(x) | |
// | |
func flatMap2<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
switch { (x1: Result<T>, f1: T -> Result<U>) -> Result<Result<U>> in | |
switch x1 { | |
case .Success(let box): return .Success(Box(f1(box.unbox))) | |
case .Failure(let err): return .Failure(err) | |
} | |
}(x, f) { | |
case .Success(let box): | |
switch box.unbox { | |
case .Success(let nestedBox): return .Success(nestedBox) | |
case .Failure(let err): return .Failure(err) | |
} | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// .Success(nestedBox) === box.unbox | |
// | |
func flatMap3<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
switch { (x1: Result<T>, f1: T -> Result<U>) -> Result<Result<U>> in | |
switch x1 { | |
case .Success(let box): return .Success(Box(f1(box.unbox))) | |
case .Failure(let err): return .Failure(err) | |
} | |
}(x, f) { | |
case .Success(let box): | |
switch box.unbox { | |
case .Success(let nestedBox): return box.unbox // <== | |
case .Failure(let err): return .Failure(err) | |
} | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// Distribute function result to cases | |
// There is a mapping of the .Success case in the first to the .Success | |
// case in the second, and similarly for the .Failure cases. So we | |
// can merge them. | |
// | |
func flatMap4<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
switch x { | |
case .Success(let box): return Box(f(box.unbox)).unbox | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// Box(x).unbox === x | |
// | |
func flatMap5<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
switch x { | |
case .Success(let box): return f(box.unbox) // <== | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// Compare to continueWith | |
// | |
func continueWith<T,U>(x: Result<T>, f: T -> Result<U>) -> Result<U> { | |
switch x { | |
case .Success(let box): return f(box.unbox) | |
case .Failure(let err): return .Failure(err) | |
} | |
} | |
// | |
// QED | |
// | |
// | |
// Support | |
// | |
import Foundation | |
enum Result<T> { | |
case Success(Box<T>) | |
case Failure(NSError) | |
} | |
final class Box<T> { | |
let unbox: T | |
init(_ value: T) { self.unbox = value } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment