Skip to content

Instantly share code, notes, and snippets.

@jmont
Last active March 30, 2016 16:27
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jmont/ce348636b64a0eb429ae to your computer and use it in GitHub Desktop.
Save jmont/ce348636b64a0eb429ae to your computer and use it in GitHub Desktop.
Swift Monads
// Swift Monads -- Maybe
// Juan C. Montemayor (@norsemelon)
// This operator can be used to chain Optional types like so:
// optionalVal >>= f1 >>= f2
// where f1 and f2 have type `Any -> Any?`
//
// If a value is ever nil, the chain short-circuits and will result in nil.
// This is a much neater way to do this than using the if syntax specified in
// the Swift iBook.
operator infix >>= { associativity left }
func >>=<TypeA, TypeB> (lhs: TypeA?, rhs: (TypeA -> TypeB?)) -> TypeB? {
if let x = lhs {
return rhs(x)
}
return nil;
}
// Just normals functions...
// Notice how no `!` or `?` operators are used.
func itWorks (y: String) -> String? { return y + " this works" }
func exclaim (y: String) -> String? { return y + "!" }
func add10 (x: Int) -> Int? { return x + 10 }
/* Chaining is much nicer with the >>= operator.... */
"I can't believe" >>= itWorks // result: {Some "I can't believe this works"}
var noWay: String? = "no way"
noWay >>= itWorks >>= exclaim // result: {Some "no way this works!"}
/* A nil in the chain will short-circuit */
noWay >>= ({ _ in return nil}) >>= exclaim // result: {nil}
noWay = nil
noWay >>= itWorks >>= exclaim // result: {nil}
/* Works for any type */
5 >>= add10 >>= add10 // result: {Some 25}
@roshanr95
Copy link

A small doubt regarding this: when you say short-circuiting, does it mean that execution stops when a nil is encountered(ignoring the rest of the chain) or the nil travels through the chain to the end without anything being done to it ?

@alexbbrown
Copy link

It short circuits in the sense that

nil as String >>= itWorks >>= exclaim

will not run the code in the braces:

 { return y + " this works" }

and

 { return y + "!" }

will not be excuted. However, for each step in the chain, it still evaluates:

    if let x = lhs {
        // skip
    }
    return nil;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment