Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import Cocoa
// MARK: Part of Your New Toolkit
func bind<T, U>(optional: T?, f: T -> U?) -> U? {
if let x = optional {
return f(x)
}
else {
return nil
}
}
/// End of a chain so that methods may return nothing and return `Void` instead of `Void?`
func bind<T>(optional: T?, f: T -> Void) -> Void {
if let x = optional {
f(x)
}
}
// MARK: The Problem Domain
struct Money {}
struct Account {}
func addTransferToLog(amount: Money, from: Account, to: Account) -> Void {
// ...
}
// If this confuses you, look up currying:
// supply `to` in code and be done with all
// required parameters; you will end up with
// a reference to a function with 2 other
// params.
// This will be the ones `withdrawCash`
// supplies and the chaining throws in
// automatically.
// Short version for:
//
// func depositCach(to: Account)
// -> (amount: Money, from: Account)
// -> (Money, Account, Account)? {...}
func depositCash(to: Account)(amount: Money, from: Account) -> (Money, Account, Account)? {
// ...
return (amount, from, to)
}
func withdrawCash(amount: Money, from: Account) -> (Money, Account)? {
// ...
return (amount, from)
}
// MARK: Usage Without Custom Operator
bind(
bind(withdrawCash(Money(), Account()),
depositCash(Account())),
addTransferToLog)
// MARK: With >>= Operator
infix operator >>= { associativity left precedence 150 }
func >>=<T, U>(optional: T?, f: T -> U?) -> U? {
return bind(optional, f)
}
func >>=<T>(optional: T?, f: T -> Void) -> Void {
bind(optional, f)
}
let amount = Money()
let fromAccount = Account()
let toAccount = Account()
withdrawCash(amount, fromAccount)
>>= depositCash(toAccount)
>>= addTransferToLog
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.