On Jan 23, 2010, at 15:31 , Adrian Adshead wrote:
If  (>>=) :: m a -> (a -> m b) -> m b

Then whenever the IO monad is entered it can not be escaped,
so in the example you gave:-

f :: IO a -> Int
f _ = 10

while f (putStrLn "foo") is a pure function evaluating to 10,
neither the IO Action, nor the a (from 'IO a') can be used without
using the (>>=) or (>>). Therefore since the parameter can not

False;  you could feed anything an IO value that doesn't otherwise reject it; the definitions of (>>) and (>>=) don't constrain where you can use an (IO a), they specify that if you use (>>) or (>>=) then you can't discard the (Monad m) context.  Since the only thing a function that takes a completely unconstrained type (a) can do is pass it through unchanged or discard the value (think about it), and the result of the main function must be (IO a), *that* limits what you can do with an (IO a).  You can pass it on (id), discard it (const, or the fancier versions of const that have been discussed in this thread), or feed it using (>>) or (>>=) to something else expecting an (IO a), or to anything else that will likewise preserve the IO encapsulation.  Control.Applicative and Control.Arrow are other mechanisms that do so; IO has an Applicative instance, and any Monad has an Arrow (Kleisli m)) instance.  Since Haskell's type system is open, it's never possible to rule out other qualifying instances.

-- 
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com
system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu
electrical and computer engineering, carnegie mellon university    KF8NH