module Basement.Compat.MonadTrans
( State(..)
, Reader(..)
) where
import Basement.Compat.Base
import Control.Monad ((>=>))
newtype State s m a = State { runState :: s -> m (a, s) }
instance Monad m => Functor (State s m) where
fmap f fa = State $ runState fa >=> (\(a, s2) -> return (f a, s2))
instance Monad m => Applicative (State s m) where
pure a = State $ \st -> return (a,st)
fab <*> fa = State $ \s1 -> do
(ab,s2) <- runState fab s1
(a,s3) <- runState fa s2
return (ab a, s3)
instance Monad m => Monad (State r m) where
return a = State $ \st -> return (a,st)
ma >>= mb = State $ \s1 -> do
(a,s2) <- runState ma s1
runState (mb a) s2
newtype Reader r m a = Reader { runReader :: r -> m a }
instance Monad m => Functor (Reader r m) where
fmap f fa = Reader $ runReader fa >=> (\a -> return (f a))
instance Monad m => Applicative (Reader r m) where
pure a = Reader $ \_ -> return a
fab <*> fa = Reader $ \r -> do
a <- runReader fa r
ab <- runReader fab r
return $ ab a
instance Monad m => Monad (Reader r m) where
return a = Reader $ \_ -> return a
ma >>= mb = Reader $ \r -> do
a <- runReader ma r
runReader (mb a) r