Skip to content

Instantly share code, notes, and snippets.

@jemmons
Last active October 25, 2022 10:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jemmons/71104d11e8598220cab48c651c8dbf4f to your computer and use it in GitHub Desktop.
Save jemmons/71104d11e8598220cab48c651c8dbf4f to your computer and use it in GitHub Desktop.
import Foundation
typealias Continuation<Ret> = (Ret) -> Void
typealias ContinuationMonad<Value> = (@escaping Continuation<Value>) -> Void
typealias Transform<T,U> = (T) -> ContinuationMonad<U>
func async<Value>(_ wrappedValue: Value) -> ContinuationMonad<Value> {
{ $0(wrappedValue) }
}
func flatMap<T,U>(_ monad: @escaping ContinuationMonad<T>, _ transform: @escaping Transform<T,U>) -> ContinuationMonad<U> {
{ continuation in
monad { wrappedValue in
transform(wrappedValue)(continuation)
}
}
}
public func curry<T, U, Z>(_ ƒ: @escaping (T, U)->Z) -> (T) -> (U) -> Z {
{ t in { u in ƒ(t, u) } }
}
precedencegroup BackApplication {
associativity: left
}
infix operator <|: BackApplication
public func <| <T, U>(ƒ: (T)->U, t: T) -> U {
ƒ(t)
}
precedencegroup FlatMapOperator {
higherThan: BackApplication
associativity: left
}
infix operator >>=: FlatMapOperator
func >>=<T,U> (lhs: @escaping ContinuationMonad<T>, rhs: @escaping Transform<T,U>) -> ContinuationMonad<U> {
flatMap(lhs, rhs)
}
func fetchAvatar(user: UUID, completion: @escaping Continuation<URL>) {
// Delay added to simulate an actual async task.
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
completion(URL(string: "/\(user.uuidString)")!)
}
}
// For the sake of demonstration, we’re pulling a
// string out of the url rather than fetching an
// image actual image.
func fetchImage(url: URL, completion: @escaping Continuation<String>) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
completion(url.path)
}
}
func fetchPortrait(user: UUID, completion: @escaping Continuation<String>) {
async(user)
>>= curry(fetchAvatar)
>>= curry(fetchImage)
<| completion
}
fetchPortrait(user: UUID()) { print($0) }
//> After two seconds, prints a UUID.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment