Applicativeスタイルの一般的な形は、以下のようになる。
f <$> m1 <*> m2 <*> m3 ...
<$> は liftM (あるいは fmap)の別名、ap は <*> の別名だと思ってよい。ap の実装を見てみると、以下のように定義してある。
ap :: (Monad m) => m (a -> b) -> m a -> m b ap = liftM2 id
最初、意味がまったく分からず、nobsun と一緒に考えた。その結果を忘れないように残しておく。
liftM2 のシグニチャと実装は以下の通り。この記事では型だけが重要である。
liftM2 :: (a -> b -> c) -> m a -> m b -> m c liftM2 f m1 m2 = do x1 <- m1 x2 <- m2 return (f x1 x2)
id の型は以下の通り。
id :: a -> a
ここで、id の型を b -> c を
id :: (b -> c) -> (b -> c)
と考え、liftM2 に代入すると、LiftM2 の a も b -> c になる訳だから、次のようになる。
liftM2 id :: m (b -> c) -> m b -> m c
という訳で、ap の型が出てきた。
ちなみに、ap の別定義として、以下がある。
ap :: (Monad m) => m (a -> b) -> m a -> m b ap = liftM2 ($)
($) の型は以下の通り。
($) :: (a -> b) -> a -> b
これは、id の変形した型と同じだ。だから、この定義でもよいことが分かる。