概要
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