Functor
Functorは文脈がついた値を写すもの。写すだとピンとこなければ文脈を損なわずに中身の値を変えれるものと考えても良い。
Maybeという「値があるかもしれないしないかもしれない」文脈に、関数をつかって中身だけ変えるなんてことができる。これを写すと表現している。
ghci> fmap (+3) (Just 3)
Just 6
ghci> fmap (+3) Nothing
Nothing
できること:通常の関数で、ファンクターの中の値を写す
Applicative Functor
文脈がついた値を文脈がついた関数で写すもの。
値だけではなく関数にも文脈がついている場合に使える
Functorの中身が関数で、その関数を別のファンクターの中の値に適応させたいって時に使う。
ghci> Just (+3) <*> Just 9 -- <*>はApplicativeの関数(後述)
Just 12
できること:ファンクターの中の関数で、別のファンクターの中の値を写す
Functorの強化版といわれる。やれることが多いFunctor。
定義
ghci> :i Applicative Functor
type Applicative :: (* -> *) -> Constraint
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
上記定義のfは全て型コンストラクタ。
fはFunctorに属してなければならない = すべてのApplicativeはfmapが使える = ApplicativeであればFunctorである。
pureはaをApplicativeにする関数 - aをApplicativeの中に入れる - aにApplicativeの文脈をつける。など表現される。 Applicativeと言ってはいるが概念としてFunctorと思っておいて良い。
Functor fmap :: (a -> b) -> f a -> f b
Applicative (<*>) :: f (a -> b) -> f a -> f b
この比較でもイメージできるかもだが、(<*>) は fmapの1個目の引数も Functorにしたもの。(a->b)関数に文脈がついているなんて表現する。
ghci> Just 3 + Just 4 -- できない
こういう文脈付きの値の中身を計算する方法はFunctorとApplicativeでそれぞれ以下。
ghci> fmap (+3) (Just 4)
Just 7
ghci> pure (+) <*> Just 3 <*> Just 4
Just 7
pure f <*> x は fmap f x と等価、この書き方はよく使う(らしい)ので中間演算子<$>が用意されている。
ghci> (+) <$> Just 3 <*> Just 4
Just 7