Skip to content

Instantly share code, notes, and snippets.

@benjohnde
Created February 23, 2018 14:48
Show Gist options
  • Save benjohnde/24827328f643bb4c4128dcb95f031c60 to your computer and use it in GitHub Desktop.
Save benjohnde/24827328f643bb4c4128dcb95f031c60 to your computer and use it in GitHub Desktop.
import Foundation
public enum Either<T, U> {
case left(T)
case right(U)
}
precedencegroup EitherChaining {
associativity: left
}
infix operator ==> : EitherChaining
@discardableResult
public func ==> <T, U, V> (either: Either<T, U>, transform: (U) -> Either<T, V>) -> Either<T, V> {
return either.flatMap(transform)
}
extension Either {
public func either<Result>(ifLeft: (T) -> Result, ifRight: (U) -> Result) -> Result {
switch self {
case let .left(x):
return ifLeft(x)
case let .right(x):
return ifRight(x)
}
}
public func map<V>(_ transform: (U) -> V) -> Either<T, V> {
return flatMap { .right(transform($0)) }
}
public func flatMap<V>(_ transform: (U) -> Either<T, V>) -> Either<T, V> {
return either(ifLeft: Either<T, V>.left, ifRight: transform)
}
}
struct BackendError: Error {
let reason: String
}
struct User {
let username: String
}
struct UserProfile {
let country: String
}
struct Connection {
}
func createBackedConnection() -> Either<BackendError, Connection> {
return .right(Connection())
}
func getUser(connection: Connection) -> Either<BackendError, User> {
let user = User(username: "ben")
return .right(user)
}
func getUserProfile(user: User) -> Either<BackendError, UserProfile> {
return .left(BackendError(reason: "Profile could not be fetched"))
}
let result1 = (createBackedConnection() ==> getUser ==> getUserProfile)
print(result1)
let result2 = createBackedConnection()
.flatMap { getUser(connection: $0) }
.flatMap { getUserProfile(user: $0) }
print(result2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment