[Haskell-cafe] Inverting a Monad
Bas van Dijk
v.dijk.bas at gmail.com
Wed Feb 6 16:47:33 EST 2008
On Feb 6, 2008 8:27 PM, Tillmann Rendel
<rendel at rbg.informatik.tu-darmstadt.de> wrote:
> 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
More information about the Haskell-Cafe
mailing list