module Airship.RST
( RST (..)
, evalRST
, execRST
, mapRST
, withRST
, failure
) where
import Control.Applicative (Alternative (..),
Applicative (..))
import Control.Category ((.))
import Control.Monad (MonadPlus (..), ap)
import Control.Monad.Base (MonadBase (..))
import Control.Monad.Reader (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Trans (MonadIO (..), MonadTrans (..))
import Control.Monad.Trans.Control (ComposeSt, MonadBaseControl (..),
MonadTransControl (..),
defaultLiftBaseWith,
defaultRestoreM)
import Data.Either
import Prelude (Functor (..), Monad (..), seq,
($), ($!))
newtype RST r s e m a = RST { runRST :: r -> s -> m (Either e a, s) }
evalRST :: Monad m => RST r s e m a -> r -> s -> m (Either e a)
evalRST m r s = do
(res, _) <- runRST m r s
return $! res
execRST :: Monad m => RST r s e m a -> r -> s -> m s
execRST m r s = do
(_,!s') <- runRST m r s
return $! s'
withRST :: Monad m => (r' -> r) -> RST r s e m a -> RST r' s e m a
withRST f m = RST $ \r' s -> runRST m (f r') s
instance (Monad m) => MonadReader r (RST r s e m) where
ask = RST $ \r s -> return $! (Right r,s)
local f m = RST $ \r s -> runRST m (f r) s
#if __GLASGOW_HASKELL__ == 708
instance (Monad m) => Functor (RST r s e m) where
fmap f m = RST $ \r s -> runRST m r s >>= helper where
helper (a, s') = case a of
(Left l) -> return $! (Left l, s')
(Right r) -> return $! (Right $ f r, s')
#else
instance (Functor m) => Functor (RST r s e m) where
fmap f m = RST $ \r s -> fmap (\(a,s') -> (fmap f a, s')) $ runRST m r s
#endif
instance Monad m => Applicative (RST r s e m) where
pure = return
(<*>) = ap
instance MonadPlus m => Alternative (RST r s e m) where
empty = mzero
(<|>) = mplus
instance (Monad m) => MonadState s (RST r s e m) where
get = RST $ \_ s -> return $! (Right s,s)
put x = RST $ \_ _ -> return $! (Right (),x)
state act = RST $ \_ s -> do
let (res, !s') = act s
return $! (Right res, s')
mapRST :: (m (Either e a, s) -> n (Either e b, s)) -> RST r s e m a -> RST r s e n b
mapRST f m = RST $ \r s -> f (runRST m r s)
rwsBind :: Monad m =>
RST r s e m a
-> (a -> RST r s e m b)
-> RST r s e m b
rwsBind m f = RST go
where
go r !s = do
(a, !s') <- runRST m r s
case a of
Left e -> return $! (Left e, s')
Right a' -> runRST (f a') r s'
instance (Monad m) => Monad (RST r s e m) where
return a = RST $ \_ s -> return $! (Right a, s)
(>>=) = rwsBind
fail msg = RST $ \_ _ -> fail msg
instance (MonadPlus m) => MonadPlus (RST r s e m) where
mzero = RST $ \_ _ -> mzero
m `mplus` n = RST $ \r s -> runRST m r s `mplus` runRST n r s
instance (MonadIO m) => MonadIO (RST r s e m) where
liftIO = lift . liftIO
instance MonadTrans (RST r s e) where
lift m = RST $ \_ s -> do
a <- m
return $ s `seq` (Right a, s)
instance MonadBase b m => MonadBase b (RST r s e m) where
liftBase = lift . liftBase
instance MonadBaseControl b m => MonadBaseControl b (RST r s e m) where
type StM (RST r s e m) a = ComposeSt (RST r s e) m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM
instance MonadTransControl (RST r s e) where
type StT (RST r s e) a = (Either e a, s)
liftWith f = RST $ \r s -> do
res <- f $ \(RST g) -> g r s
return $! (Right res, s)
restoreT k = RST $ \_ _ -> k
failure :: Monad m => e -> RST r s e m a
failure e = RST $ \_ s -> return $! (Left e, s)