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 functor or map.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Box<T> {
    var content: T
    init(content: T) {
        self.content = content
    }

    func functor<U>(_ relation: (T) -> U) -> Box<U> {
        return Box<U>(content: relation(self.content))
    }
}

func functor<T, U>(box: Box<T>, relation: (T) -> U) -> Box<U> {
    return Box(content: relation(box.content))
}

let a = Box(content: 1)
let b = functor(box: a, relation: { $0 + 100 }).content
b // 101

And we can chain functors like this.

1
2
3
let addup: (Int)->Int = { $0 + 1 }
let c = a.functor(addup).functor(addup).content
c // 3

We can also do it like Haskell

1
2
3
4
5
6
7
8
9
10
precedencegroup chainopts {
    associativity: left
}
infix operator <^>: chainopts
func <^><T, U>(a: Box<T>, f: (T) -> U) -> Box<U> {
    return a.functor(f)
}

let d = a <^> addup <^> addup
d.content // 3

Monad

$C$ is a Monad if $C$ has the following ability. This is also called as flatmap.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Box<T> {
    var content: T
    init(content: T) {
        self.content = content
    }

    func monad<U>(_ relation: (T) -> Box<U>) -> Box<U> {
        return relation(self.content)
    }
}

func monad<T, U>(box: Box<T>, relation: (T) -> Box<U>) -> Box<U> {
    return relation(box.content)
}

let e = monad(box: a, relation: { Box(content: $0 + 1000) } ).content
e // 1001
let addupAndWrap: (Int)->Box<Int> = { Box(content: $0 + 1000) }
let f = a.monad(addupAndWrap).monad(addupAndWrap).content
f // 2001

Haskell-like version.

1
2
3
4
5
6
infix operator >>-: chainopts
func >>-<T, U>(a: Box<T>, f: (T) -> Box<U>) -> Box<U> {
    return a.monad(f)
}
let g = a >>- addupAndWrap >>- addupAndWrap
g.content // 2001

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
class Box<T> {
    var content: T
    init(content: T) {
        self.content = content
    }

    func apply<U>(_ relation: Box<(T) -> U>) -> Box<U> {
        return Box<U>(content: relation.content(self.content))
    }
}

func apply<T, U>(box: Box<T>, relation: Box<(T) -> U>) -> Box<U> {
    return Box(content: relation.content(box.content))
}

let h = apply(box: a, relation: Box(content: {$0 + 10000} )).content
h // 10001
let anBoxContainsAddup: Box<(Int)->Int> = Box(content: {$0 + 10000} )
let i = a.apply(anBoxContainsAddup).apply(anBoxContainsAddup).content
i // 20001

Haskell-like version.

1
2
3
4
5
6
infix operator <*>: chainopts
func <*><T, U>(a: Box<T>, f: Box<(T) -> U>) -> Box<U> {
    return a.apply(f)
}
let j = a <*> anBoxContainsAddup <*> anBoxContainsAddup
j.content // 20001

Comments