Skip to content

Instantly share code, notes, and snippets.

@rnapier
Created September 7, 2014 13:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnapier/b383d2542c9fabe913c9 to your computer and use it in GitHub Desktop.
Save rnapier/b383d2542c9fabe913c9 to your computer and use it in GitHub Desktop.
Proof: flatMap<Result> and continueWith are the the same function
// 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