module System.Console.Haskeline.Monads( module System.Console.Haskeline.MonadException, MonadTrans(..), MonadIO(..), ReaderT(..), runReaderT', mapReaderT, asks, StateT, runStateT, evalStateT', mapStateT, gets, modify, update, MonadReader(..), MonadState(..), MaybeT(..), orElse ) where import Control.Monad (liftM) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.Trans.Maybe (MaybeT(..)) import Control.Monad.Trans.Reader hiding (ask,asks) import qualified Control.Monad.Trans.Reader as Reader import Data.IORef #if __GLASGOW_HASKELL__ < 705 import Prelude hiding (catch) #endif import System.Console.Haskeline.MonadException 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 mapStateT :: (forall b . m b -> n b) -> StateT s m a -> StateT s n a mapStateT f (StateT m) = StateT (\s -> f (m s)) 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') makeStateT :: Monad m => (s -> m (a,s)) -> StateT s m a makeStateT f = StateT $ \s -> do (x,s') <- f s return $ \g -> g 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 -- ReaderT (IORef s) is better than StateT s for some applications, -- since StateT loses its state after an exception such as ctrl-c. instance MonadIO m => MonadState s (ReaderT (IORef s) m) where get = ask >>= liftIO . readIORef put s = ask >>= liftIO . flip writeIORef s 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 controlIO f = makeStateT $ \s -> controlIO $ \run -> fmap (flip runStateT s) $ f $ stateRunIO s run where stateRunIO :: s -> RunIO m -> RunIO (StateT s m) stateRunIO s (RunIO run) = RunIO (\m -> fmap (makeStateT . const) $ run (runStateT m s)) orElse :: Monad m => MaybeT m a -> m a -> m a orElse (MaybeT f) g = f >>= maybe g return