Loop over monadic binds

I’ve got some code that I brute forced like this:

do
  let i1 = 0
  i2 <- fn i1
  i3 <- fn i2
  i4 <- fn i3
  i5 <- fn i4
  pure [i1, i2, i3, i4, i5]

or

  let i1 = 0 
  in
    fn i1 >>= \i2 ->
      fn i2 >>= \i3 ->
        fn i3 >>= \i4 ->
          fn i4 >>= \i5 ->
            pure [i1, i2, i3, i4, i5]

but with even more iterations than that. Clearly, it calls for some sort of loop, but I’m having a tough time though figuring out how to do that when I’m inside a monad already. I think it would just be a fold over >>= fn if I could throw away the value at each iteration, but then I can’t see how to assemble the answer at the end. Any pointers?

Thanks in advance!

take a look at foldM

Ah, thank you! That’s the pointer I needed to get unstuck. I used it to arrive at a solution:

  reverse . toList <$> foldM foldFn (0 :| []) [1 .. n]
  
  where 
    foldFn (i' :| is) _elem = do
      i <- fn i'
      pure (i :| i':is)

but then I played with it some more and figured out how to solve it with recursion so I could do a right fold instead of left:

  (0:) <$> go 0 iterations
  where 
    go _ 0 = pure []
    go i n = do
      i' <- fn i
      (i':) <$> go i' (n-1)