request-monad-0.1.0.0: src/Control/Monad/Request/Class.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{- |
Module : Control.Monad.Request.Class
Copyright : (c) Tom Hulihan <hulihan.tom159@gmail.com> 2014,
License : MIT
Maintainer : hulihan.tom159@gmail.com
Stability : experimental
Portability : non-portable (multi-parameter type classes)
[Computation type:] Compuations that send requests and handle responses
[Binding strategy:] Response callbacks are composed with the binding function
[Useful for:] Implementation-agnostic requests (i.e. making real requests versus
mocking), adding middlewares.
[Example type:] @'Control.Monad.Request.Lazy.Request' String String a@
The Request monad
-}
module Control.Monad.Request.Class ( MonadRequest(..) ) where
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.Cont as Cont
import Control.Monad.Trans.Identity as Identity
import Control.Monad.Trans.Error as Error
import Control.Monad.Trans.Except as Except
import Control.Monad.Trans.List as List
import Control.Monad.Trans.Maybe as Maybe
import Control.Monad.Trans.RWS.Lazy as RWSL
import Control.Monad.Trans.RWS.Strict as RWSS
import Control.Monad.Trans.Reader as Reader
import Control.Monad.Trans.State.Lazy as StateL
import Control.Monad.Trans.State.Strict as StateS
import Control.Monad.Trans.Writer.Lazy as WriterL
import Control.Monad.Trans.Writer.Strict as WriterS
import Data.Monoid
-- | This type class generalizes monadic requests.
--
-- Parameters:
--
-- * @r@ - The type of request
--
-- * @r'@ - The type of response
--
-- * @m@ - The monad through which the requests are sent
--
class Monad m => MonadRequest r r' m | m -> r r' where
-- | Given a request of type @r@, perform an action in @m@ whose result is
-- @r'@.
send :: r -> m r'
instance MonadRequest r r' m => MonadRequest r r' (IdentityT m) where
send = IdentityT . send
instance (MonadRequest r r' m) => MonadRequest r r' (ContT x m) where
send = lift . send
instance (Error e, MonadRequest r r' m) => MonadRequest r r' (ErrorT e m) where
send = ErrorT . liftM Right . send
instance MonadRequest r r' m => MonadRequest r r' (ExceptT e m) where
send = ExceptT . liftM Right . send
instance MonadRequest r r' m => MonadRequest r r' (ListT m) where
send = ListT . liftM (\x -> [x]) . send
instance MonadRequest r r' m => MonadRequest r r' (MaybeT m) where
send = MaybeT . liftM Just . send
instance (Monoid w, MonadRequest r r' m) => MonadRequest r r' (RWSL.RWST x w s m) where
send = lift . send
instance (Monoid w, MonadRequest r r' m) => MonadRequest r r' (RWSS.RWST x w s m) where
send = lift . send
instance MonadRequest r r' m => MonadRequest r r' (ReaderT x m) where
send = ReaderT . const . send
instance MonadRequest r r' m => MonadRequest r r' (StateL.StateT x m) where
send r = StateL.StateT $ \s -> send r >>= \a -> return (a, s)
instance MonadRequest r r' m => MonadRequest r r' (StateS.StateT x m) where
send r = StateS.StateT $ \s -> send r >>= \a -> return (a, s)
instance (Monoid w, MonadRequest r r' m) => MonadRequest r r' (WriterL.WriterT w m) where
send = WriterL.WriterT . liftM (flip (,) mempty) . send
instance (Monoid w, MonadRequest r r' m) => MonadRequest r r' (WriterS.WriterT w m) where
send = WriterS.WriterT . liftM (flip (,) mempty) . send