module Control.Monad.Request.Lazy (
MonadRequest(..)
, Request
, request
, runRequest
, mapRequest
, mapResponse
, RequestT
, requestT
, runRequestT
, mapRequestT
, mapResponseT
) where
import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Request.Class
import Control.Monad.Trans.Class
import Control.Monad.Error.Class
import Control.Monad.RWS.Class
import Data.Monoid
import Data.Functor.Identity
type Request r r' = RequestT r r' Identity
request :: r
-> (r' -> a)
-> Request r r' a
request r g = requestT r (Identity . g)
runRequest :: Request r r' a
-> (r -> r')
-> a
runRequest act f = runIdentity $ runRequestT act (Identity . f)
mapRequest :: (x -> r)
-> Request x r' a
-> Request r r' a
mapRequest f = mapRequestT (return . f)
mapResponse :: (r' -> x)
-> Request r x a
-> Request r r' a
mapResponse f = mapResponseT (return . f)
data RequestT r r' m a
= Pure a
| Request r (r' -> RequestT r r' m a)
| Lift (m (RequestT r r' m a))
requestT :: Monad m => r
-> (r' -> m a)
-> RequestT r r' m a
requestT r g = Request r (Lift . liftM Pure . g)
runRequestT :: Monad m => RequestT r r' m a
-> (r -> m r')
-> m a
runRequestT m req =
let go (Pure a) = return a
go (Request r g) = req r >>= go . g
go (Lift act) = act >>= go
in go m
mapRequestT :: Monad m => (x -> RequestT r r' m r)
-> RequestT x r' m a
-> RequestT r r' m a
mapRequestT f =
let go (Pure a) = Pure a
go (Request x g) = f x >>= flip Request (go . g)
go (Lift act) = Lift (liftM go act)
in go
mapResponseT :: Monad m => (r' -> RequestT r r' m x)
-> RequestT r x m a
-> RequestT r r' m a
mapResponseT f =
let go (Pure a) = Pure a
go (Request r g) = Request r (go . g <=< f)
go (Lift act) = Lift (liftM go act)
in go
instance Alternative m => Alternative (RequestT r r' m) where
empty = Lift empty
(<|>) =
let go (Pure a) _ = Pure a
go (Request r g) x = Request r (flip go x . g)
go (Lift act) x = Lift (fmap (flip go x) act)
in go
instance Applicative m => Applicative (RequestT r r' m) where
pure = Pure
(<*>) =
let go (Pure f) (Pure a) = Pure (f a)
go (Request r g) x = Request r (flip go x . g)
go (Lift act) x = Lift (fmap (flip go x) act)
go x (Request r g) = Request r (go x . g)
go x (Lift act) = Lift (fmap (go x) act)
in go
instance Functor m => Functor (RequestT r r' m) where
fmap f =
let go (Pure a) = Pure (f a)
go (Request r g) = Request r (go . g)
go (Lift act) = Lift (fmap go act)
in go
instance Monad m => Monad (RequestT r r' m) where
return = Pure
fail = Lift . fail
(>>=) m f =
let go (Pure a) = f a
go (Request r g) = Request r (go . g)
go (Lift act) = Lift (liftM go act)
in go m
instance MonadPlus m => MonadPlus (RequestT r r' m) where
mzero = Lift mzero
mplus =
let go (Pure a) _ = Pure a
go (Request r g) x = Request r (flip go x . g)
go (Lift act) x = Lift (liftM (flip go x) act)
in go
instance Monad m => MonadRequest r r' (RequestT r r' m) where
send = flip Request Pure
instance MonadIO m => MonadIO (RequestT r r' m) where
liftIO = lift . liftIO
instance MonadTrans (RequestT r r') where
lift = Lift . liftM Pure
instance MonadError e m => MonadError e (RequestT r r' m) where
throwError = Lift . throwError
catchError m h =
let go (Pure a) = Pure a
go (Request r g) = Request r (go . g)
go (Lift act) = Lift (catchError act (return . h))
in go m
instance MonadReader x m => MonadReader x (RequestT r r' m) where
ask = lift ask
local f =
let go (Pure a) = Pure a
go (Request r g) = Request r (go . g)
go (Lift act) = Lift (liftM go (local f act))
in go
instance (Monoid w, MonadReader r m, MonadWriter w m, MonadState s m) => MonadRWS r w s (RequestT r r' m)
instance MonadState s m => MonadState s (RequestT r r' m) where
get = lift get
put = lift . put
instance (Monoid w, MonadWriter w m) => MonadWriter w (RequestT r r' m) where
writer = lift . writer
tell = lift . tell
listen =
let go acc (Pure a) = Pure (a, acc)
go acc (Request r g) = Request r (go acc . g)
go acc (Lift act) = Lift $ do
~(m, w) <- listen act
return (go (acc `mappend` w) m)
in go mempty
pass m = listen m >>= \ ~(~(a, f), w) -> writer (a, f w)