.. 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

Reply via email to