Shishir,
I'll reply as an humble programmer, not a category theorist. For me the clarifying example was to contrast
putStrLn (getLine ++ getLine)
with
s = square 3 + square 4
where
square x = x * x
There is absolutely nothing that "leaks" between the two sub-expressions involving square, so I'm free to rewrite as:
a = square 3
b = square 4
s = a + b
or
or
x = square 7
hh m n = square m + square n
without altering the value of s or any surrounding computation. In that last case, I can now freely intermingle uses of hh and square without risk.
But if I were to attempt the same gymnastics with putStrLn and getLine, I wouldn't have those freedoms. The order of evaluation/performance now becomes critical.
So the monad provides a way to manage the composition, and the type system ensures visibility to the fact that something more is going on when a defined function includes IO behavior.
Hope that helps,
-jn-