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.Fix,
module Control.Monad.Trans,
) where
import Prelude
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
#if __GLASGOW_HASKELL__ < 710
import Data.Foldable
import Data.Traversable (Traversable(traverse))
#endif
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)