Reputation: 20653
How can reverse2lines
transformed into the using >>=
syntax ? Just like addOneInt
is transformed into addOneInt'
?
addOneInt :: IO ()
addOneInt = do line <- getLine
putStrLn (show (1 + read line :: Int))
addOneInt' :: IO ()
addOneInt' = getLine >>= \line ->
putStrLn (show ( 1 + read line :: Int))
reverse2lines :: IO ()
reverse2lines =
do line1 <- getLine
line2 <- getLine
putStrLn (reverse line2)
putStrLn (reverse line1)
Please also consider reading the follow up question and its valuable answers.
Upvotes: 1
Views: 209
Reputation: 20653
Here is the code from Will's very nice answer using only >>=
:
reverse2lines' :: IO ()
reverse2lines' =
getLine >>= (\line1 ->
getLine >>= (\line2 ->
putStrLn (reverse line2) >>= (\_ ->
putStrLn (reverse line1) )))
Lesson learned : the sequencing in do
corresponds simply to nesting of lambda expressions.
Upvotes: 1
Reputation: 71119
You could safely deduce it from what you already know. Start by fully parenthesizing your addOneInt'
:
addOneInt' = getLine >>= (\line ->
putStrLn (show (1 + read line :: Int)) )
Next, you reverse2lines
can be equivalently written as
reverse2lines =
do { line1 <- getLine ;
do { line2 <- getLine ;
do { putStrLn (reverse line2) ;
do { putStrLn (reverse line1) } } } }
Applying the one-step transformation that you already used for addOneInt
, as much times as needed, you'd get
reverse2lines' :: IO ()
reverse2lines' =
getLine >>= (\line1 ->
getLine >>= (\line2 ->
putStrLn (reverse line2) >>
putStrLn (reverse line1) ) )
Syntactically, the parentheses around lambda expressions can be omitted, but writing them explicitly here helps to clarify and make obvious the nested structure of these functions, especially if we'd line up the indentation.
Full translation arranges for the monad's fail
function to be called on pattern mismatch, but since the variable patterns (line1
, line2
) are irrefutable, this translation is in fact exact.
Upvotes: 5
Reputation: 3428
Statements of type x <- m
can be translated as m >>= \x -> ...
, and statements in which the return value isn't bound like m
can be translated as m >> ...
reverse2lines :: IO ()
reverse2lines = getLine
>>= \line1 -> getLine
>>= \line2 -> putStrLn (reverse line2)
>> putStrLn (reverse line1)
The translation isn't exact - the fail
monad function complicates things a little. You can read about it here, but as far as I know it's irrelevant when dealing with the IO
monad.
Upvotes: 4