
On Feb 6, 2008 8:27 PM, Tillmann Rendel
What about this?
inv :: MonadError e m => m a -> m () inv m = join $ (m >> return mzero) `catchError` \_ -> return (return ())
Beautiful! That's the one I'm looking for! I was already defining a 'MonadInvert' class and a bunch of instances like below but this is a much more flexible solution. ------------------------------------------------------------------------------------------------- -- | A Monad that supports inversion. -- Turning success into failure and failure into success. class Monad m => MonadInvert m where -- | @invert m@ fails when @m@ is successfull (returns a value) -- and returns @()@ when @m@ fails . invert :: m a -> m () instance MonadInvert Maybe where invert Nothing = Just () invert (Just _) = Nothing instance MonadInvert [] where invert [] = [()] invert (_:_) = [] instance E.Error e => MonadInvert (Either e) where invert (Left _) = Right () invert (Right _) = Left E.noMsg instance (E.Error e, MonadInvert m) => MonadInvert (E.ErrorT e m) where invert = T.lift . invert . E.runErrorT instance MonadInvert m => MonadInvert (S.StateT st m) where invert m = S.StateT $ \s -> (invert $ S.runStateT m s) >>= \u -> return (u, s) ... ------------------------------------------------------------------------------------------------- Thanks very much. Bas