cambraca
cambraca

Reputation: 27835

"Iterating until" with monads

I have something like this, which is working:

main = do
  let p = something :: MyType
  p' <- newP p
  p'' <- newP p'
  p''' <- newP p''
  print p'''

See the pattern? I want to repeat this until a certain condition is met, or until a maximum number of iterations passed.

I found Control.Monad.Loops.iterateUntil, but I can't get it to work. Here's the code I have (check looks something like this check :: MyType -> Bool):

main = do
  let p = something :: MyType
  let stopCondition (i, p) = i == 100 || check p
  let run (i, p) = (i + 1, newP p)
  p' <- iterateUntil stopCondition (run (0, p))
  print p'

It doesn't even compile.

Note that it's important that each time this thing runs, the result of run is fed to the next iteration (I'm not sure iterateUntil will do that).

Upvotes: 1

Views: 314

Answers (1)

Lee
Lee

Reputation: 144136

It looks like you want to use iterateUntilM which has type (a -> Bool) -> (a -> m a) -> a -> m a, where the state type a is (Int, MyType). Then run should look like:

let run (i, p) = fmap (\p' -> (i + 1, p')) (newP p)

then you can do

(_, p') <- iterateUntilM stopCondition run (0, p)

Upvotes: 4

Related Questions