SciTech.blog
SciTech.blog

Applicative functors in Swift

17 Oct 2017, 01:30 • swift, monads

Applicative functors are less general than functors but more general than monads, which makes them useful in some scenarios. Swift is sufficiently functional to admit a straightforward implementation.

Let’s implement Maybe. Swift already has this type (called Optional) so the below code is only illustrative.

Maybe is functorial and can be equipped with the apply method which applies a function of type Maybe⟨T→U⟩ to Maybe⟨T⟩ returning Maybe⟨U⟩.

enum Maybe<T> {
    case None
    case Some(T)
    func fmap<U>(_ f:(T)->U) -> Maybe<U> {
        return bind{.Some(f($0))}
    }
    func bind<U>(_ f:(T)->Maybe<U>) -> Maybe<U> {
        switch self {
        case .None: return .None
        case let .Some(x): return f(x)
        }
    }
    func apply<U>(_ mf:Maybe<(T)->U>) -> Maybe<U> {
        switch mf {
        case .None: fatalError()
        case let .Some(f): return fmap(f)
        }
    }
}

infix operator </>
func </><T,U>(f:(T)->U, m:Maybe<T>) -> Maybe<U> {
    return m.fmap(f)
}

apply is usually used as an operator denoted by ⟨*⟩:

infix operator <*>
func <*><T,U>(f:Maybe<(T)->U>, m:Maybe<T>) -> Maybe<U> {
    return m.apply(f)
}

As an example, consider the + function, which can be thought of as a unary function of type \(A \rightarrow (A \rightarrow A)\). What we get when we fmap it to a monadic value is a unary function but it’s now wrapped in Maybe so we need ⟨*⟩ in order to apply it to a (monadic) value:

let m1 = Maybe.Some(2)
print(m1)
let f = { x in { y in x + y} } </> m1
let m2 = f <*> Maybe.Some(3)
print(m2)

Comments

Name: