Take the 2-minute tour ×

Consider the following Haskell code:

import Control.Monad.State

test :: Int -> [(Int, Int)]
test = runStateT $ do
    a <- lift [1..10]
    modify (+a)
    return a

main = print . test $ 10

This produces the following output:


However I would like to produce the following output instead:


This is easy to do in an impure language like JavaScript:

function test(state) {
    var result = [];

    for (var a = 1; a <= 10; a++) {
        result.push([a, state += a]);

    return result;

How do you do the same thing in Haskell?

share|improve this question

2 Answers 2

up vote 6 down vote accepted

The Haskell types and the logic of your JavaScript code doesn't match: the JS code has two values in the state (the Int, and the returned list). In contrast, StateT Int [] a doesn't really have a list in the state; rather, it runs stateful actions multiple times (with the initial state unchanged for each run) and collects all the results in a list.

In other words, the JS code has type State (Int, [(Int, Int)]) [(Int, Int)]. But this is too literal a translation and we can write more elegant Haskell code.

Sticking to the State monad, we can return a list with mapM or forM:

test2 :: Int -> [(Int, Int)]
test2 = evalState $ 
    forM [1..10] $ \a -> do
        s <- get <* modify (+a)
        return (a, s) 

Some lens magic can make it more similar to the JS code:

{-# LANGUAGE TupleSections #-}

import Control.Lens

test3 :: Int -> [(Int, Int)]
test3 = evalState $ 
    forM [1..10] $ \a -> (a,) <$> (id <+= a)

However, we can do away with State altogether, and it's the best approach here, I think:

import Control.Monad (ap)

test4 :: Int -> [(Int, Int)]
test4 n = ap zip (tail . scanl (+) n) [1..10]
-- or without ap : zip [1..10] (drop 1 $ scanl (+) n [1..10])
share|improve this answer
The function forM is exactly what I needed to sequence my State actions. Thank you. –  Aadit M Shah Apr 6 '14 at 14:30
You can avoid the TupleSections and the lambda : \a -> (a,) is exactly (,). –  Nicolas Apr 7 '14 at 6:48

Your series is quadratic and can be generated more simply:

series = fmap (\x -> (x, quot (x*x + x) 2 + 10)) [1..]

If you want a recurrence relation you might write it as this:

series :: [(Int,Int)]
series = let
  series' x y = (x, x + y) : series' (x + 1) (x + y)
  in series' 1 10

There is no compelling reason that I see to use monads.

share|improve this answer

Your Answer


