Blog

Functional Snippet #7: Applicative Functors

In last week’s snippet we used a login function like this as an example:

func login(email: String, pw: String, success: Bool -> ())

Often you’ll have the situation that the strings you want to hand to the login function are optional values. Then you’d have to write something like this:

if let email = getEmail() {
    if let pw = getPw() {
        login(email, pw) { println("success: \($0)") }
    } else {
        // error...
    }
} else {
    // error...
}

There’s another way to tackle these situations: we can make use of the fact that optionals in Swift are an instance of applicative functors. Yes, that sounds confusing and crazy, but don’t worry, we’ll simply make an example. For applicative functors, such as optionals, we can define the <*> operator:

infix operator <*> { associativity left precedence 150 }
func <*><A, B>(lhs: (A -> B)?, rhs: A?) -> B? {
    if let lhs1 = lhs {
        if let rhs1 = rhs {
            return lhs1(rhs1)
        }
    }
    return nil
}

In short, this operator takes the right hand operand and applies it to the function on the left hand side if neither of them is nil. Using this operator and the curry function from last week’s snippet we can write the example from above like this:

if let f = curry(login) <*> getEmail() <*> getPw() {
    f { println("success \($0)") }
} else {
    // error...
}

Much nicer, isn’t it? Admittedly, it looks pretty foreign at first, but it’s a wonderful opportunity to practice some out of the box thinking!

Update: in snippet 18, we show how this can be improved with Swift 1.2’s multiple optional unwrapping.

Stay up-to-date with our newsletter or follow us on Twitter.

Back to the Blog

recent posts