LoginSignup
2
3

More than 5 years have passed since last update.

Functor < Applicative < Monad

Last updated at Posted at 2015-03-30

学習の素材は、
すごいHaskellたのしく学ぼう!


以前、Functor < Applicative < Monad という関係性があると書いたもののその根拠を問われると、その時点の知識では より柔軟に計算を行える、という理解しかなかった。今回学びを進めていくうちにもう少し具体的に表せることがわかった。

より柔軟に計算を行える?

より柔軟に計算を行えるというのは、Monad 型クラスは、FunctorApplicative を内包しており、さらに便利な関数も持っていてより実用的な対処ができる ということが言いたかった。ところが、Monadはサブクラスなどの型制約を持っておらず、内包しているかどうかはぱっと見ではわからない状態だった。

調べてみると、これはMonad が Haskell に導入されたのは Applicative よりもずっと前だったという背景が理由にあるらしい。ではどのような考えから、 Functor < Applicative < Monad と言えるのだろうか。

Functor < Applicative

これは、コードから明らかで、Functor のサブクラスとして Applicative があり、Applicativefmap に加えて <*> などのアプリカティブ・スタイルがあり、文脈をもった関数をアプリカティブ値に対して続けざまに適用できるので、より実用的である。

class Functor f => Applicative f where
    -- | Lift a value.
    pure :: a -> f a

    -- | Sequential application.
    (<*>) :: f (a -> b) -> f a -> f b

    -- | Sequence actions, discarding the value of the first argument.
    (*>) :: f a -> f b -> f b
    a1 *> a2 = (id <$ a1) <*> a2
    -- This is essentially the same as liftA2 (const id), but if the
    -- Functor instance has an optimized (<$), we want to use that instead.

    -- | Sequence actions, discarding the value of the second argument.
    (<*) :: f a -> f b -> f a
    (<*) = liftA2 const

Applicative < Monad

Monad には、型クラス制約がないため、別の手段でfmap<*> などと等価な関数を用意しなくてはならない。やはりその通りで、それぞれに対応した関数として、liftMap があった。

fmapと同等
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
<*>と同等
ap :: Monad m => m (a -> b) -> m a -> m b
pureと同等
return :: Monad m => a -> m a

Monad はこのほかにも、バインド(>>=) を持っていて、文脈をもった値を相互作用させる力も持っている。つまり、MonadFunctor であり Applicative であり、プラスαである。

Functor < Applicative < Monad

これで、MonadApplicative よりも実用的だと、その実装からも説明できるようになった。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3