liveBook · Manning

Do notation

As explained in Learn Haskell by Example

Do notation, or a do block, is Haskell syntax for sequencing monadic computations and binding their intermediate results.

Do notation is Haskell syntax for building one larger action from smaller monadic actions. A `do` block runs actions in written order, lets later steps use earlier results, and keeps interaction with the environment inside an `IO` action rather than a pure function. section 3.1.1 section 3.5

Read and echo a line

`<-` evaluates an action at that point and binds its produced value. Here `getLine` produces a `String`, which `putStrLn` consumes; the final statement gives the whole block type `IO ()`. `main = do` ` line <- getLine` ` putStrLn line` section 3.1.1

A line without `<-` sequences an action whose result is not needed. Use `_ <-` when deliberately discarding a result. `return` wraps a value in an action; it does not exit the block. Because the final expression determines an action's result, conditional branches inside an `IO` block must both produce compatible IO actions. section 3.1.3 section 3.5

Loop until empty input

A recursive action can read input, stop with `return ()`, or create a nested `do` block to perform several actions before recurring. `interactiveLines counter = do` ` line <- getLine` ` if null line` ` then return ()` ` else do` ` putStrLn (show counter ++ ". " ++ line)` ` interactiveLines (counter + 1)` section 3.1.3

Do notation applies beyond `IO`: it is syntactic sugar for monadic bind. `do x <- m; f x` corresponds to `m >>= f`, while `do _ <- m1; m2` corresponds to `m1 >> m2`. In parsers, this makes dependencies between parsed values explicit; failure in an earlier parser short-circuits the remaining work. section 12.1.5 section 12.1.5

do x <- m
   f x

Compare a single binding written with `>>=` and with `do` notation. section 12.1.5

How Learn Haskell by Example covers it

How deep it goes
Defines IO-block behavior first, then relates the syntax to monadic bind and Parser implementation.
Examples
Uses an echo program, a recursive numbered-input loop, monadic addition, and PNM-header parsers.
What it assumes
Starts with simple IO actions and introduces monadic generalization later through bind and Parser.
What you can do after
Apply it via Haskell IO and Parser actions to sequence work, bind results, and handle action-valued branches.
How it connects
Connects IO actions, pure functions, recursion, return, Monad, bind, and Parser.

Also explained in

Compare how 2 books explain do notation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.