Swapnil B.
Swapnil B.

Reputation: 769

Converting the do notation to bind notation

How do I convert the below Haskell do notation to the bind (>>=) notation?

rev2lines :: IO ()
rev2lines = do line1 <- getLine
               line2 <- getLine
               putStrLn (reverse line2)
               putStrLn (reverse line1)

I am a Haskell beginner with decent knowledge and I tried something like

getLine >>= (\line1 -> getLine >>= (\line2 -> putStrLn $ reverse(line2)))

but I am not able to include the print statement for the other line i.e. line1. Kindly help me to understand this concept properly.

Upvotes: 10

Views: 814

Answers (3)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477533

The putStrLn has type IO (), so we can construct a dummy variable _ as a way to obtain the unit type () and so keep processing, so:

rev2lines = getLine >>=
                (\line1 -> getLine >>=
                    (\line2 -> putStrLn (reverse line2) >>=
                        (\_ -> putStrLn (reverse line1))
                    )
                )

Since the pattern f >>= \_ -> g occurs quite often, there is the (>>) :: Monad m => m a -> m b -> m b operator such that f >> g is semantically the same as f >>= (\_ -> g), so a shorter form is:

rev2lines = getLine >>=
                (\line1 -> getLine >>=
                    (\line2 -> putStrLn (reverse line2) >>
                        (putStrLn (reverse line1))
                    )
                )

Upvotes: 6

melpomene
melpomene

Reputation: 85877

Assuming you meant

rev2lines = do
           line1 <- getLine
           line2 <- getLine
           putStrLn (reverse line2)
           putStrLn (reverse line1)

the desugaring looks like

rev2lines =
           getLine >>= \line1 ->
           getLine >>= \line2 ->
           putStrLn (reverse line2) >>
           putStrLn (reverse line1)

which parses as

rev2lines =
    getLine >>= (
        \line1 -> getLine >>= (
            \line2 -> (putStrLn (reverse line2)) >> (putStrLn (reverse line1))))

Upvotes: 7

chi
chi

Reputation: 116174

You're almost there: you need to use >>.

getLine >>= (\line1 -> 
getLine >>= (\line2 -> 
putStrLn (reverse line2) >>
putStrLn (reverse line1)
))

Note that >> ... is equivalent to >>= (\_ -> ...), so you can also use that if you prefer.

Similarly, your block

 do line1 <- getLine
    line2 <- getLine
    putStrLn (reverse line2)
    putStrLn (reverse line1)

is equivalent to

 do line1 <- getLine
    line2 <- getLine
    _ <- putStrLn (reverse line2)
    putStrLn (reverse line1)

Essentially, any entry in the block (but the last one) which has no explicit <- uses >> (or, if you prefer, has an implicit _ <- in front).

Upvotes: 11

Related Questions