概要
Functorとは構造内の値に関数を適用できるもので、
Functor: (a -> b) -> f a -> f b
である。とはどういうことか。
圏論について
圏論とは、数学的な構造を持った「対象」と、対象間の「射」からなる。
関数 f が Int を引数に取り String を返すとすると、 f: Int -> String と表記できる。この場合、Int, String など(一般的に型と呼ばれるもの)は「対象」であり、 f は「射」である。
a -> b -> c とは
HaskellやLISP, OCaml などの関数型言語を考える。関数型は、関数が第一級であり、関数が射であると同時に対象でもある。また、Haskellなどにおいて、関数は、引数(対象)をひとつ取り、返り値を1つ返す。
では、引数を2つ以上取りたい場合はどうするか。具体的には、 f(x, y) = x + y なる関数を定義したいという欲求が出てくる。ここで登場するのが f: a -> b -> c (関数のカリー化)である。
分かりやすいように、f: Int -> Int -> Int とする。これは、f: Int -> (Int -> Int) という意味である。 f に Int を渡すと、 g: Int -> Int という関数が返ってくる。これに対してさらに Int を渡すと、 Int が返ってくる。
f(x: Int) = g(y: Int) = x + y
g = f(2) // = g(y: Int) = 2 + y
g(3) // = 5
f に 2 を渡すと、yを受け取って+2をする関数 が返ってくるので、そいつに更に 3 を渡します。これで足し算を実現しています。つまり、
f(2)(3) // = 5
構造体とは
Scalaの List[String] とかを考える。(Scalaは純粋関数型ではなく、クラスが関数 - 正確にはメソッド - を持つので特殊だが)
list = List("first", "second", "third")
list(0) // => "first"
Scalaにおいて、 list(0) は list.apply(0) のことである。
list.apply は Int -> String となる。
この apply のような、構造体から値を取り出すような操作を extract と言う。
Map[String, String] の extract は String -> String である。
Functor とは
Functorとは構造内の値に関数を適用できるもので、Functor: (a -> b) -> f a -> f b である。
FunctorはScalaでいう map である。Scalaのmapの実装を見てみると
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
いかにも Functor っぽい感じになっている。
(a -> b) -> f a -> f b とは (a -> b) -> (f a -> f b) となる。ここにおける、 f というのが List であり、Functorは、関数 a -> b を受け取り、構造体の中身に a -> b を適用し、構造体を返す。
次
次は Applicative