Earlier I asked about translating monadic code to use only the applicative functor instance of Parsec. Unfortunately I got several replies which answered the question I lite
You can view functors, applicatives and monads like this: They all carry a kind of "effect" and a "value". (Note that the terms "effect" and "value" are only approximations - there doesn't actually need to be any side effects or values - like in Identity or Const.)
Functor you can modify possible values inside using fmap, but you cannot do anything with effects inside.With Applicative, you can create a value without any effect with pure, and you can sequence effects and combine their values inside. But the effects and values are separate: When sequencing effects, an effect cannot depend on the value of a previous one. This is reflected in <*, <*> and *>: They sequence effects and combine their values, but you cannot examine the values inside in any way.
You could define Applicative using this alternative set of functions:
fmap :: (a -> b) -> (f a -> f b)
pureUnit :: f ()
pair :: f a -> f b -> f (a, b)
-- or even with a more suggestive type (f a, f b) -> f (a, b)
(where pureUnit doesn't carry any effect)
and define pure and <*> from them (and vice versa). Here pair sequences two effects and remembers the values of both of them. This definition expresses the fact that Applicative is a monoidal functor.
Now consider an arbitrary (finite) expression consisting of pair, fmap, pureUnit and some primitive applicative values. We have several rules we can use:
fmap f . fmap g ==> fmap (f . g)
pair (fmap f x) y ==> fmap (\(a,b) -> (f a, b)) (pair x y)
pair x (fmap f y) ==> -- similar
pair pureUnit y ==> fmap (\b -> ((), b)) y
pair x pureUnit ==> -- similar
pair (pair x y) z ==> pair x (pair y z)
Using these rules, we can reorder pairs, push fmaps outwards and eliminate pureUnits, so eventually such expression can be converted into
fmap pureFunction (x1 `pair` x2 `pair` ... `pair` xn)
or
fmap pureFunction pureUnit
So indeed, we can first collect all effects together using pair and then modify the resulting value inside using a pure function.
With Monad, an effect can depend on the value of a previous monadic value. This makes them so powerful.