module Control.Monad.Except.Backtracking (
BExceptT(),
bExceptT,
runBExceptT,
hoistEither,
module Control.Monad.Error.Class
)where
import Control.Monad.Trans.Either hiding (hoistEither)
import Control.Monad.Codensity
import Control.Monad.Trans.Class
import Control.Applicative
import Data.Functor.Bind
import Control.Monad.Free.Class
import Control.Monad.IO.Class
import Control.Monad.Reader.Class
import Control.Monad.State.Class
import Control.Monad.State.Lazy
import Control.Monad.Error.Class
import Control.Monad.Writer.Class
import Control.Monad.RWS.Class
import Control.Monad.Except
import Data.Functor.Alt
import Data.Functor.Plus
import Data.Semigroup
import Control.Monad
newtype BExceptT e m a = BExceptT {
unwrapBExceptT' :: Codensity (EitherT e m) a } deriving
(Functor, Applicative, Monad, Apply, MonadIO)
bExceptT :: (Monad m) => m (Either e a) -> BExceptT e m a
bExceptT = BExceptT . lift . EitherT
runBExceptT :: (Monad m) => BExceptT e m a -> m (Either e a)
runBExceptT = runEitherT . lowerCodensity . unwrapBExceptT'
unwrapBExceptT :: (Monad m) =>
BExceptT e m a -> forall b. (a -> EitherT e m b) -> EitherT e m b
unwrapBExceptT = runCodensity . unwrapBExceptT'
instance (Functor f, MonadFree f m) =>
MonadFree f (BExceptT e m) where
wrap t = BExceptT $ Codensity $ \h -> wrap $
fmap (\p -> unwrapBExceptT p h) t
instance MonadTrans (BExceptT e) where
lift = BExceptT . lift . lift
instance (MonadReader r m) => MonadReader r (BExceptT e m) where
ask = lift ask
local f = bExceptT . local f . runBExceptT
reader = lift . reader
instance (MonadState s m) => MonadState s (BExceptT e m) where
get = lift get
put = lift . put
state = lift . state
instance (Functor m, MonadWriter w m) => MonadWriter w (BExceptT e m) where
writer = lift . writer
tell = lift . tell
listen = bExceptT . fmap f . listen . runBExceptT where
f (Left e, _) = Left e
f (Right a, w) = Right (a, w)
pass = bExceptT . pass . fmap f . runBExceptT where
f (Left e) = (Left e, id)
f (Right (a, f)) = (Right a, f)
instance (Functor m, MonadRWS r w s m) => MonadRWS r w s (BExceptT e m)
instance (Monad m) => MonadError e (BExceptT e m) where
throwError e = BExceptT $ lift $ throwError e
catchError m handler = BExceptT $ Codensity $ \c ->
unwrapBExceptT m c `catchError` handler' c where
handler' c e = unwrapBExceptT (handler e) c
instance (Monad m, Semigroup e) => Alt (BExceptT e m) where
a <!> b = catchError a $ \e -> catchError b $ \e' ->
throwError $ e <> e'
instance (Monad m, Semigroup e, Monoid e) => Plus (BExceptT e m) where
zero = throwError mempty
instance (Monad m, Semigroup e, Monoid e) =>
Alternative (BExceptT e m) where
(<|>) = (<!>)
empty = zero
instance (Monad m, Semigroup e, Monoid e) =>
MonadPlus (BExceptT e m) where
mplus = (<!>)
mzero = zero
hoistEither :: (Monad m) => Either e a -> BExceptT e m a
hoistEither = bExceptT . return