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
I'd like to add/reword a couple things to the very helpful existing answers:
Applicatives are "static". In pure f <*> a <*> b, b does not depend on a, and so can be analyzed statically. This is what I was trying to show in my answer to your previous question (but I guess I failed -- sorry) -- that since there was actually no sequential dependence of parsers, there was no need for monads.
The key difference that monads bring to the table is (>>=) :: Monad m => m a -> (a -> m b) -> m a, or, alternatively, join :: Monad m => m (m a). Note that whenever you have x <- y inside do notation, you're using >>=. These say that monads allow you to use a value "inside" a monad to produce a new monad, "dynamically". This cannot be done with an Applicative. Examples:
-- parse two in a row of the same character
char >>= \c1 ->
char >>= \c2 ->
guard (c1 == c2) >>
return c1
-- parse a digit followed by a number of chars equal to that digit
-- assuming: 1) `digit`s value is an Int,
-- 2) there's a `manyN` combinator
-- examples: "3abcdef" -> Just {rest: "def", chars: "abc"}
-- "14abcdef" -> Nothing
digit >>= \d ->
manyN d char
-- note how the value from the first parser is pumped into
-- creating the second parser
-- creating 'half' of a cartesian product
[1 .. 10] >>= \x ->
[1 .. x] >>= \y ->
return (x, y)
Lastly, Applicatives enable lifted function application as mentioned by @WillNess.
To try to get an idea of what the "intermediate" results look like, you can look at the parallels between normal and lifted function application. Assuming add2 = (+) :: Int -> Int -> Int:
-- normal function application
add2 :: Int -> Int -> Int
add2 3 :: Int -> Int
(add2 3) 4 :: Int
-- lifted function application
pure add2 :: [] (Int -> Int -> Int)
pure add2 <*> pure 3 :: [] (Int -> Int)
pure add2 <*> pure 3 <*> pure 4 :: [] Int
-- more useful example
[(+1), (*2)]
[(+1), (*2)] <*> [1 .. 5]
[(+1), (*2)] <*> [1 .. 5] <*> [3 .. 8]
Unfortunately, you can't meaningfully print the result of pure add2 <*> pure 3 for the same reason that you can't for add2 ... frustrating. You may also want to look at the Identity and its typeclass instances to get a handle on Applicatives.