Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting the do notation to bind notation

Tags:

haskell

monads

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.

like image 840
Swapnil B. Avatar asked Apr 21 '18 20:04

Swapnil B.


People also ask

How does do work in Haskell?

Do notations are simply designed to handle the IO operations in Haskell. To represent the do notation, we can simply use the 'do' keyword; after this, we can write our code that we want to execute. In most common general coding practice for Haskell, it usually comes up with the main module.

What is bind Haskell?

In Haskell, there is an operator bind, or ( >>= ) that allows for this monadic composition in a more elegant form similar to function composition. halve :: Int -> Maybe Int halve x | even x = Just (x `div` 2) | odd x = Nothing -- This code halves x twice.

What is a Haskell Monad?

What is a Monad? A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.


2 Answers

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).

like image 172
chi Avatar answered Oct 05 '22 00:10

chi


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))))
like image 44
melpomene Avatar answered Oct 04 '22 23:10

melpomene