
Intuitively it seems like the applicative expression: (++) <$> getLine <*> getLine should represent the same thing as the more traditional liftM2 expressions: do { x <- getLine; y <- getLine; return ((++) x y) } but it seems to me that you cant directly manipulate the first into the second. I get: do x2' <- getLine x1 <- return ((++) x2') x2 <- getLine return (x1 x2) the only way I can get from here to the liftM2 definition is if I treat "x1 <- return ((++) x2')" as "let x1 = (++) x2", and then allow it to be reordered after the second getLine. Then it is straightforward to reduce to the liftM2 expression above. It seems to me that this is a valid transformation if: - no side effects, including pattern match errors, can occur in the let (or x1 <- return ...). - movement doesnt change the dependencies - x1 isnt used between the original line and its new position - there are no new bindings for x2' introduced between the original line and the new line. Did I overlook anything? Do any haskell implementations allow rewrites like these to occur? Tim Newsham http://www.thenewsh.com/~newsham/