Do Notation
In this lesson, we study do-notation, a more convenient way to chain IO actions.
We'll cover the following
In the last lesson, we learned how to perform IO
operations in Haskell and separate them from pure code. We also saw how to combine IO
operations in sequence by using the >>
and >>=
operators. But chaining many IO
actions this way tends to look clumsy and unreadable, especially when many >>=
operators and lambdas are involved. Luckily, Haskell offers a syntactic sugar variant for this called do
-notation.
Introducing do
-notation.
As an example, let’s take a simple program that asks the user to enter two numbers and add them, combining several IO
actions.
addInput :: IO ()
addInput = putStrLn "What's your first number?"
>> readLn
>>= \first -> (
putStrLn "What's your second number?"
>> readLn
>>= \second -> putStrLn ("The sum is " ++ (show (first + second)) ++ "!")
)
With the nested lambda expressions capturing the output of readLn
, this becomes tricky to decipher at first glance. We could split it into several functions to improve readability, but a simpler solution is to use do
-notation.
addInput :: IO ()
addInput = do
putStrLn "What's your first number?"
first <- readLn
putStrLn "What's your second number?"
second <- readLn
putStrLn ("The sum is " ++ (show (first + second)) ++ ".")
To use do
-notation, we write do
to the right side of a function equation and then put each IO
action we want to use on a single line. For IO
actions that return an output that we want to use (like getLine
), we can bind the output to a variable like in first <- getLine
. The String
yielded by getLine :: IO String
will be bound to first
, which can then be used in later IO
actions.
Here is a terminal in which you can run the addInput
IO action.
Get hands-on with 1200+ tech skills courses.