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.