[Haskell-cafe] reordering pure bindings in monads

Tim Newsham newsham at lava.net
Thu May 29 23:15:19 EDT 2008

Intuitively it seems like the applicative expression:

   (++) <$> getLine <*> getLine

should represent the same thing as the more traditional liftM2 

   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

More information about the Haskell-Cafe mailing list