module System.Console.Haskeline.Monads( module Control.Monad.Trans, module System.Console.Haskeline.MonadException, ReaderT(..), runReaderT', asks, StateT, runStateT, evalStateT', gets, modify, update, MonadReader(..), MonadState(..), MaybeT(..), orElse ) where import Control.Monad.Trans import System.Console.Haskeline.MonadException import Prelude hiding (catch) import Control.Monad.Reader hiding (MonadReader,ask,asks,local) import qualified Control.Monad.Reader as Reader class Monad m => MonadReader r m where ask :: m r instance Monad m => MonadReader r (ReaderT r m) where ask = Reader.ask instance Monad m => MonadReader s (StateT s m) where ask = get instance (MonadReader r m, MonadTrans t, Monad (t m)) => MonadReader r (t m) where ask = lift ask asks :: MonadReader r m => (r -> a) -> m a asks f = liftM f ask class Monad m => MonadState s m where get :: m s put :: s -> m () gets :: MonadState s m => (s -> a) -> m a gets f = liftM f get modify :: MonadState s m => (s -> s) -> m () modify f = get >>= put . f update :: MonadState s m => (s -> (a,s)) -> m a update f = do s <- get let (x,s') = f s put s' return x runReaderT' :: Monad m => r -> ReaderT r m a -> m a runReaderT' = flip runReaderT newtype StateT s m a = StateT { getStateTFunc :: forall r . s -> m ((a -> s -> r) -> r)} instance Monad m => Monad (StateT s m) where return x = StateT $ \s -> return $ \f -> f x s StateT f >>= g = StateT $ \s -> do useX <- f s useX $ \x s' -> getStateTFunc (g x) s' instance MonadTrans (StateT s) where lift m = StateT $ \s -> do x <- m return $ \f -> f x s instance MonadIO m => MonadIO (StateT s m) where liftIO = lift . liftIO runStateT :: Monad m => StateT s m a -> s -> m (a, s) runStateT f s = do useXS <- getStateTFunc f s return $ useXS $ \x s' -> (x,s') instance Monad m => MonadState s (StateT s m) where get = StateT $ \s -> return $ \f -> f s s put s = s `seq` StateT $ \_ -> return $ \f -> f () s instance (MonadState s m, MonadTrans t, Monad (t m)) => MonadState s (t m) where get = lift get put = lift . put evalStateT' :: Monad m => s -> StateT s m a -> m a evalStateT' s f = liftM fst $ runStateT f s instance MonadException m => MonadException (StateT s m) where block m = StateT $ \s -> block $ getStateTFunc m s unblock m = StateT $ \s -> unblock $ getStateTFunc m s catch f h = StateT $ \s -> catch (getStateTFunc f s) $ \e -> getStateTFunc (h e) s newtype MaybeT m a = MaybeT { unMaybeT :: m (Maybe a) } instance Monad m => Monad (MaybeT m) where return x = MaybeT $ return $ Just x MaybeT f >>= g = MaybeT $ f >>= maybe (return Nothing) (unMaybeT . g) instance MonadIO m => MonadIO (MaybeT m) where liftIO = lift . liftIO instance MonadTrans MaybeT where lift = MaybeT . liftM Just instance MonadException m => MonadException (MaybeT m) where block = MaybeT . block . unMaybeT unblock = MaybeT . unblock . unMaybeT catch f h = MaybeT $ catch (unMaybeT f) $ unMaybeT . h orElse :: Monad m => MaybeT m a -> m a -> m a orElse (MaybeT f) g = f >>= maybe g return instance Monad m => MonadPlus (MaybeT m) where mzero = MaybeT $ return Nothing MaybeT f `mplus` MaybeT g = MaybeT $ f >>= maybe g (return . Just)