SwiftでFunctor型を書いてみる

Functorとは

構造内の値に関数を適用できるものである。

しかし、これだけを聞いてもわかりづらい。

この記事では、HaskellのFunctorを参考にSwiftのOptionalを用いてFunctorを理解していきたい。

HaskellのFunctor

class Functor f where 
    fmap:: (a-> b) -> f a -> fb 

Functor型は、一つの関数fmapを持つクラスである。

fは、aやbのような具体型ではなく、一つの型引数を受け取る型コンストラクタだ。

  具体型 : 型引数を一つも取らない全ての型引数が埋まっている型

  型コンストラクタは、一つの型引数を取って具体型になるもの。

  型コンストラクタの例としてリストがあげられる。

  リストは、[]では具体型ではなく、[Int]となって具体型になるからだ。

つまり、fa -> fb ということから、fという構造を持ったままa型 -> b型に関数を適用していることがわかる。

Swiftでの実装

Optionalも型コンストラクタなので、

SwiftのOptionalを使って、Functorの実装を行なっていくことにする。

まずは、Functor型を作っていく。

protocol Functor {
    associatedtype A
    associatedtype B
    associatedtype F
    func fmap(f: ((A) -> B)) -> F
}
enum FunctorOptional<T>: Functor {
    typealias A = T
    typealias B = T
    typealias F = FunctorOptional

    case some(value: T)
    case none

    func fmap(f: ((A) -> B)) -> F{
        switch self {
        case .some(let value):
            return .some(value: f(value))
        case .none:
            return .none
        }
    }
}

let value = FunctorOptional.some(value: 1)
let notValue = FunctorOptional<Int>.none

print(value.fmap(f: { $0 + 2} ))
print(notValue.fmap(f: { $0 + 2 }))

//some(value: 3)
//none
 

OptionalにもMapが用意されているため、実装に置いてのメリットは提示できないが、fmapを使っての実装を書くことができた。