Translate between >>= and do

In Haskell, do notation and >>= notation can be interchangeable ways to express the same goal.

To start, let’s define example types and functions to use for illustration. The example code is adapted from the Haskell Wikibook1, § 32.3. (It is a free book, and I heartily recommend it compared to as a beginner’s book.)

type Board = Int -- represents current game configuration

-- returns the possible game board configurations for the next turn.
nextConfigs :: Board -> [Board]
nextConfigs bd = [bd + 1, bd * 10]

For simplicity in the example, there are always exactly two next turn configurations, and the next configurations always use the formula [+1, *10].

To find the list of possible game configurations after one turn we do:

ghci> bd = 3 :: Board -- a sample board to work with
ghci> nextConfigs bd
[4, 30]

To find the list of possible game configurations after three turns we can do:

ghci> nextConfigs bd >>= nextConfigs >>= nextConfigs

How can this be translated to do notation?

Translation: Overview

Start with >>= notation.

nextConfigs bd >>= nextConfigs >>= nextConfigs

This is equivalently:2

nextConfigs bd >>= (\x -> nextConfigs x) >>= (\y -> nextConfigs y)

Now we translate to do notation:

  x <- nextConfigs bd
  y <- nextConfigs x
  nextConfigs y

Compare the last two code snippets visually.

The lambda argument names x and y in >>= notation become the assignment variable names x and y in do notation. The nextConfigs function calls in >>= notation are written one per line in do notation.

Translation: Step-by-step

  1. Start a do block. Begin scanning the >>= notation line from left to right.
  2. Write down the first function call you encounter.
      nextConfigs bd
  3. Add an arrow when you encounter >>=.
      <- nextConfigs bd
  4. Write the name of the lambda argument, and move to the next line.
      x <- nextConfigs bd
  5. Repeat steps 2 through 4 until you reach the end of the >>= notation line.

Side Notes

What are the types of the assignment variables x and y in do notation? If one thought <- to be similar to the assignment operator = in C, then one would think the types to be [Board] since that is the return type of nextConfigs.

But the types of x and y are not [Board]. Their types are Board, which is the same as the type of x and y in the lambda arguments in >>= notation.

To get some inuition try adding this debug line in the middle of the do block.

  traceM (show x) -- from Debug.Trace

Also try the code with other monads such as Maybe.

nextConfigs :: Board -> Maybe Board
nextConfigs bd = Just (bd + 1)

  2. This is true because (\x -> nextConfigs x) is equivalent to nextConfigs