Welcome to FutureAppLaboratory

v=(*^ワ^*)=v

Functor, Monad, Applicative in Swift

| Comments

Some Implementation in Swift.

Functor

Let $C$ be a constructor which takes a variable as parameter.

$C$ is a Functor if $C$ has the following ability.

For example, we can write such a function map for Optional. (Well, swift already has such built-in function.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
extension Optional {
    func map<U>(f: Wrapped -> U) -> U? {
        switch self {
            case .Some(let x): return f(x)
            case .None: return .None
        }
    }

    // take out the wrapped item
    func toValue() -> Wrapped? {
        switch self {
            case .Some(let x): return x
            case .None: return .None
        }
    }
}

// A -> B
func plusTwo(addend: Int) -> Double {
    return Double(addend) + 2.0
}

// C[A] -> C[B]
Int?.Some(3).map(plusTwo) // Change Optional<Int>(3) into Optional<Double>(5.0)

And we can chain functors like this.

1
2
3
4
5
func plusThree(addend: Int) -> Int {
    return addend + 3
}

Int?.Some(3).map(plusThree).map(plusTwo)

We can also do it like Haskell

1
2
3
4
5
6
7
8
// This is a custom operator
infix operator <^> { associativity left }
func <^><T, U>(a: T?, f: T -> U) -> U? {
    return a.map(f)
}

Optional.Some(2) <^> plusThree // Int?(5)
Optional.Some(2) <^> plusThree <^> plusThree // Int?(8)

Monad

$C$ is a Monad if $C$ has the following ability.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
extension Optional {
    func flatMap<U>(f: Wrapped -> U?) -> U? {
        switch self {
            case .Some(let x): return f(x)
            case .None: return .None
        }
    }
}

func half(a: Int) -> Int? {
    return a % 2 == 0 ? a / 2 : .None
}

Int?.Some(4).flatMap(half) // Int?(2)

Haskell-like version.

1
2
3
4
5
6
7
8
infix operator >>- { associativity left }

func >>-<T, U>(a: T?, f: T -> U?) -> U? {
    return a.flatMap(f)
}

Int?(3) >>- half // Optional.None
Int?(4) >>- half >>- half // Int?(2)

Applicative

$C$ is a Applicative if $C$ has the following ability.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
extension Optional {
    // Note that function `f` is ALSO wrapped in Optional type
    func apply<U>(f: (Wrapped -> U)?) -> U? {
        switch f {
        case .Some(let someF): return self.map(someF)
        case .None: return .None
        }
    }
}

extension Array {
    // Note that function `f` is ALSO wrapped in Array type
    func apply<U>(fs: [Element -> U]) -> [U] {
        var result = [U]()
        for f in fs {
            for element in self.map(f) {
                result.append(element)
            }
        }
        return result
    }
}

// This is a IntFunction? type
let plusThreeBox = Optional<IntFunction>.Some(plusThree)

Int?.Some(3).apply(plusThreeBox) // Int?(6)

[1, 2, 3].apply( [ {$0 + 10}, {$0 + 100} ] ) // [11, 12, 13, 101, 102, 103]

Haskell-like version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
infix operator <*> { associativity left }

func <*><T, U>(a: T?, f: (T -> U)?) -> U? {
    return a.apply(f)
}

func <*><T, U>(a: [T], f: [T -> U]) -> [U] {
    return a.apply(f)
}

(Optional.Some(2) <*> Optional.Some({ $0 + 3 }))
// => 5

[1, 2, 3] <*> [ { $0 + 3 }, { $0 * 2 } ]
// => [ 4, 5, 6, 2, 4, 6 ]

Comments