module Control.Monad.Exceptable(
MonadError(..),
Exceptable,
exceptable,
runExceptable,
mapExceptable,
withExceptable,
makeExceptableT,
ExceptableT(ExceptableT),
unExceptableT,
runExceptableT,
mapExceptableT,
withExceptableT,
throwE,
catchE,
liftCallCC,
liftListen,
liftPass,
Except.Except,
Except.ExceptT,
module Control.Monad,
module Control.Monad.Fix,
module Control.Monad.Trans,
) where
import qualified Control.Monad.Trans.Except as Except
import Control.Monad.Trans
import Control.Monad.Signatures
import Data.Functor.Classes
import Data.Functor.Identity
import Control.Monad.State.Class as State
import Control.Monad.Error.Class as Error
import Control.Applicative
import Control.Monad
import Control.Monad.Fix
import Data.Foldable
import Data.Traversable (Traversable(traverse))
type Exceptable e = ExceptableT e Identity
except :: Either e a -> Exceptable e a
except m = makeExceptableT (Identity m)
exceptable :: Except.Except e a -> Exceptable e a
exceptable = ExceptableT
runExceptable :: Exceptable e a -> Either e a
runExceptable (ExceptableT m) = runIdentity $ Except.runExceptT m
mapExceptable :: (Either e a -> Either e' b)
-> Exceptable e a
-> Exceptable e' b
mapExceptable f = mapExceptableT (Identity . f . runIdentity)
withExceptable :: (e -> e') -> Exceptable e a -> Exceptable e' a
withExceptable = withExceptableT
newtype ExceptableT e m a = ExceptableT { unExceptableT :: Except.ExceptT e m a }
deriving (
Eq,
Eq1,
Ord,
Ord1,
Functor,
Foldable,
Applicative,
Alternative,
Monad,
MonadPlus,
MonadTrans,
MonadIO
)
instance MonadState s m => MonadState s (ExceptableT e m) where
get = lift get
put = lift . put
state = lift . state
instance Monad m => MonadError e (ExceptableT e m) where
throwError = throwE
catchError = catchE
instance (Traversable f) => Traversable (ExceptableT e f) where
traverse f a =
(ExceptableT . Except.ExceptT) <$>
traverse (either (pure . Left) (fmap Right . f)) (runExceptableT a)
instance (Read e, Read1 m, Read a) => Read (ExceptableT e m a) where
readsPrec = readsData $ readsUnary1 "ExceptableT" ExceptableT
instance (Show e, Show1 m, Show a) => Show (ExceptableT e m a) where
showsPrec d (ExceptableT m) = showsUnary1 "ExceptableT" d m
instance (Read e, Read1 m) => Read1 (ExceptableT e m) where readsPrec1 = readsPrec
instance (Show e, Show1 m) => Show1 (ExceptableT e m) where showsPrec1 = showsPrec
runExceptableT :: ExceptableT e m a -> m (Either e a)
runExceptableT = Except.runExceptT . unExceptableT
makeExceptableT :: m (Either e a) -> ExceptableT e m a
makeExceptableT = ExceptableT . Except.ExceptT
mapExceptableT :: (m (Either e a) -> n (Either e' b))
-> ExceptableT e m a
-> ExceptableT e' n b
mapExceptableT f m = makeExceptableT $ f (runExceptableT m)
withExceptableT :: (Functor m) => (e -> e') -> ExceptableT e m a -> ExceptableT e' m a
withExceptableT f = mapExceptableT $ fmap $ either (Left . f) Right
throwE :: (Monad m) => e -> ExceptableT e m a
throwE = makeExceptableT . return . Left
catchE :: (Monad m) =>
ExceptableT e m a
-> (e -> ExceptableT e' m a)
-> ExceptableT e' m a
m `catchE` h = makeExceptableT $ do
a <- runExceptableT m
case a of
Left l -> runExceptableT (h l)
Right r -> return (Right r)
liftCallCC :: CallCC m (Either e a) (Either e b) -> CallCC (ExceptableT e m) a b
liftCallCC callCC f = makeExceptableT $
callCC $ \ c ->
runExceptableT (f (\ a -> makeExceptableT $ c (Right a)))
liftListen :: (Monad m) => Listen w m (Either e a) -> Listen w (ExceptableT e m) a
liftListen listen = mapExceptableT $ \ m -> do
(a, w) <- listen m
return $! fmap (\ r -> (r, w)) a
liftPass :: (Monad m) => Pass w m (Either e a) -> Pass w (ExceptableT e m) a
liftPass pass = mapExceptableT $ \ m -> pass $ do
a <- m
return $! case a of
Left l -> (Left l, id)
Right (r, f) -> (Right r, f)