
On Sat, May 02, 2009 at 05:31:03PM +0100, Paul Keir wrote:
On the wiki page for Applicative Functors (http://www.haskell.org/haskellwiki/Applicative_functor) a familiar characteristic of monads is quoted; that they "allow you to run actions depending on the outcomes of earlier actions". I feel comfortable with Functors and Applicative Functors, but I don't yet get that "extra power" that monads provide.
An example immediately follows that quotation on the wiki:
do text <- getLine if null text then putStrLn "You refuse to enter something?" else putStrLn ("You entered " ++ text)
For simplicity's sake, I modified it to avoid using the IO monad; the "text" binding is now provided by the first parameter, and (=<<) is used due to its similarity to fmap:
bar :: Monad m => m String -> m String bar as = (=<<) (\a -> if null a then return "nothing" else return "something") as
This simplification does not preserve the crucial aspect of the example: (putStrLn "blah") has an effect (namely, printing something on the screen), whereas (return "blah") never has an effect (whatever "effect" means for the particular monad in question). You seem to be confusing the return value of a monadic computation with its side effects. In the case of 'putStrLn "blah"', the return value is (), and the side effect is to print "blah" to the screen; in the case of 'return "blah"', the return value is "blah" and there are no side effects. Since IO is a monad, we can compute the result of 'getLine' and then use it to decide which of the two putStrLns to run; the effect of the other one (printing something on the screen) will never happen. But there is no way to do this with only the Applicative interface. Try writing a function f :: IO String -> IO () -> IO () -> IO () which has the same behavior as the 'do text <- getLine...' example above, using *only* the Applicative instance of IO; you won't be able to do it. Depending how you implement f, it may execute only the first IO (), or only the second, or both, or neither; but it will always be the same. You won't be able to have f choose which to execute based on the result of the IO String parameter. -Brent