.. that don't have `MonadPlus` instance. The difference is that `MonadError` computations must be run at least once.
Signed-off-by: Petr Pudlak <[email protected]> --- src/Ganeti/Utils/MonadPlus.hs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Ganeti/Utils/MonadPlus.hs b/src/Ganeti/Utils/MonadPlus.hs index 3596d95..5e3dda2 100644 --- a/src/Ganeti/Utils/MonadPlus.hs +++ b/src/Ganeti/Utils/MonadPlus.hs @@ -35,9 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. module Ganeti.Utils.MonadPlus ( mretryN , retryMaybeN + , retryErrorN ) where import Control.Monad +import Control.Monad.Error import Control.Monad.Trans.Maybe -- | Retries the given action up to @n@ times. @@ -49,3 +51,12 @@ mretryN n = msum . flip map [1..n] -- The action signals failure by 'mzero'. retryMaybeN :: (Monad m) => Int -> (Int -> MaybeT m a) -> m (Maybe a) retryMaybeN = (runMaybeT .) . mretryN + +-- | Retries the given action up to @n@ times until it succeeds. +-- If all actions fail, the error of the last one is returned. +-- The action is always run at least once, even if @n@ is less than 1. +retryErrorN :: (MonadError e m) => Int -> (Int -> m a) -> m a +retryErrorN n f = loop 1 + where + loop i | i < n = catchError (f i) (const $ loop (i + 1)) + | otherwise = f i -- 2.2.0.rc0.207.ga3a616c
