Home > OS >  Haskell iterate (f :: IO a -> IO a)
Haskell iterate (f :: IO a -> IO a)

Time:10-07

I wrote this small program and I am a bit confused about its behaviour:

main = sequence $ iterate (printAdd =<<) (pure 0)

printAdd x = do
  l <- getLine
  let y = x   read l
  print y
  pure  y

I expected it to print the sum of all integers, every time I enter a new one. It does work more or less, but the accumulator is reset to 0 repeatedly. This reset happens after the first input, after the third input, after the sixth input and so on (i.e. it always works for one input more than previously).

Why does this happen?

How can I prevent it from happening?

CodePudding user response:

iterate gives you a list of progressively longer chains of printAdd.


iterate returns a list, where every element is given by applying the function to the previous element. In the docs you can see this illustration:

iterate f x == [x, f x, f (f x), ...]

In your case, f = (printAdd =<<) and x = pure 0. Therefore, your list would look like this:

iterate (printAdd =<<) (pure 0) = 
  [pure 0, (printAdd =<< pure 0), (printAdd =<< printAdd =<< pure 0), ...]

Every Nth element will be a chain of N printAdd calls chained together, with a zero fed into the first one

And then sequence just executes all those elements in order. The zero-th one does nothing, the first one reads one number and prints it, the second one reads a number, prints, then reads another number, then prints the sum, and so on. Every Nth element reads N numbers and prints their rolling sums.

  • Related