happstack-server-7.5.1.1: Web related tools and services.

Safe HaskellNone
LanguageHaskell2010

Happstack.Server.Monads

Contents

Description

This module provides four classes and some related functions which provide ServerPartT with much of its web-centric behavior.

  1. ServerMonad provides access to the HTTP Request
  2. FilterMonad provides the ability to apply filters and transformations to a Response
  3. WebMonad provides a way to escape a computation early and return a Response
  4. HasRqData which provides access to the decoded QUERY_STRING and request body/form data

Synopsis

ServerPartT

data ServerPartT m a Source #

ServerPartT is a rich, featureful monad for web development.

see also: simpleHTTP, ServerMonad, FilterMonad, WebMonad, and HasRqData

Instances

MonadTrans ServerPartT Source # 

Methods

lift :: Monad m => m a -> ServerPartT m a #

MonadTransControl ServerPartT Source # 

Associated Types

type StT (ServerPartT :: (* -> *) -> * -> *) a :: * #

Methods

liftWith :: Monad m => (Run ServerPartT -> m a) -> ServerPartT m a #

restoreT :: Monad m => m (StT ServerPartT a) -> ServerPartT m a #

MonadBase b m => MonadBase b (ServerPartT m) Source # 

Methods

liftBase :: b α -> ServerPartT m α #

MonadBaseControl b m => MonadBaseControl b (ServerPartT m) Source # 

Associated Types

type StM (ServerPartT m :: * -> *) a :: * #

Methods

liftBaseWith :: (RunInBase (ServerPartT m) b -> b a) -> ServerPartT m a #

restoreM :: StM (ServerPartT m) a -> ServerPartT m a #

(Monad m, MonadWriter w m) => MonadWriter w (ServerPartT m) Source # 

Methods

writer :: (a, w) -> ServerPartT m a #

tell :: w -> ServerPartT m () #

listen :: ServerPartT m a -> ServerPartT m (a, w) #

pass :: ServerPartT m (a, w -> w) -> ServerPartT m a #

(Monad m, MonadState s m) => MonadState s (ServerPartT m) Source # 

Methods

get :: ServerPartT m s #

put :: s -> ServerPartT m () #

state :: (s -> (a, s)) -> ServerPartT m a #

(Monad m, MonadReader r m) => MonadReader r (ServerPartT m) Source # 

Methods

ask :: ServerPartT m r #

local :: (r -> r) -> ServerPartT m a -> ServerPartT m a #

reader :: (r -> a) -> ServerPartT m a #

(Monad m, MonadError e m) => MonadError e (ServerPartT m) Source # 

Methods

throwError :: e -> ServerPartT m a #

catchError :: ServerPartT m a -> (e -> ServerPartT m a) -> ServerPartT m a #

Monad m => WebMonad Response (ServerPartT m) Source # 
Monad m => FilterMonad Response (ServerPartT m) Source # 
Monad m => Monad (ServerPartT m) Source # 

Methods

(>>=) :: ServerPartT m a -> (a -> ServerPartT m b) -> ServerPartT m b #

(>>) :: ServerPartT m a -> ServerPartT m b -> ServerPartT m b #

return :: a -> ServerPartT m a #

fail :: String -> ServerPartT m a #

Functor m => Functor (ServerPartT m) Source # 

Methods

fmap :: (a -> b) -> ServerPartT m a -> ServerPartT m b #

(<$) :: a -> ServerPartT m b -> ServerPartT m a #

(Monad m, Functor m) => Applicative (ServerPartT m) Source # 

Methods

pure :: a -> ServerPartT m a #

(<*>) :: ServerPartT m (a -> b) -> ServerPartT m a -> ServerPartT m b #

liftA2 :: (a -> b -> c) -> ServerPartT m a -> ServerPartT m b -> ServerPartT m c #

(*>) :: ServerPartT m a -> ServerPartT m b -> ServerPartT m b #

(<*) :: ServerPartT m a -> ServerPartT m b -> ServerPartT m a #

MonadIO m => MonadIO (ServerPartT m) Source # 

Methods

liftIO :: IO a -> ServerPartT m a #

(Functor m, MonadPlus m) => Alternative (ServerPartT m) Source # 

Methods

empty :: ServerPartT m a #

(<|>) :: ServerPartT m a -> ServerPartT m a -> ServerPartT m a #

some :: ServerPartT m a -> ServerPartT m [a] #

many :: ServerPartT m a -> ServerPartT m [a] #

MonadPlus m => MonadPlus (ServerPartT m) Source # 

Methods

mzero :: ServerPartT m a #

mplus :: ServerPartT m a -> ServerPartT m a -> ServerPartT m a #

MonadThrow m => MonadThrow (ServerPartT m) Source # 

Methods

throwM :: Exception e => e -> ServerPartT m a #

MonadCatch m => MonadCatch (ServerPartT m) Source # 

Methods

catch :: Exception e => ServerPartT m a -> (e -> ServerPartT m a) -> ServerPartT m a #

Monad m => ServerMonad (ServerPartT m) Source # 
(MonadIO m, MonadPlus m) => HasRqData (ServerPartT m) Source # 
(Functor m, Monad m, MonadPlus m, MonadIO m) => Happstack (ServerPartT m) Source # 
(Monad m, MonadPlus m) => Semigroup (ServerPartT m a) Source # 

Methods

(<>) :: ServerPartT m a -> ServerPartT m a -> ServerPartT m a #

sconcat :: NonEmpty (ServerPartT m a) -> ServerPartT m a #

stimes :: Integral b => b -> ServerPartT m a -> ServerPartT m a #

(Monad m, MonadPlus m) => Monoid (ServerPartT m a) Source # 

Methods

mempty :: ServerPartT m a #

mappend :: ServerPartT m a -> ServerPartT m a -> ServerPartT m a #

mconcat :: [ServerPartT m a] -> ServerPartT m a #

type StT ServerPartT a Source # 
type StM (ServerPartT m) a Source # 

type ServerPart a = ServerPartT IO a Source #

An alias for ServerPartT IO

Happstack class

class (ServerMonad m, WebMonad Response m, FilterMonad Response m, MonadIO m, MonadPlus m, HasRqData m, Monad m, Functor m, Applicative m, Alternative m) => Happstack m Source #

A class alias for all the classes a standard server monad (such as ServerPartT) is expected to have instances for. This allows you to keep your type signatures shorter and easier to understand.

ServerMonad

class Monad m => ServerMonad m where Source #

The ServerMonad class provides methods for reading or locally modifying the Request. It is essentially a specialized version of the MonadReader class. Providing the unique names, askRq and localRq makes it easier to use ServerPartT and ReaderT together.

Minimal complete definition

askRq, localRq

Methods

askRq :: m Request Source #

localRq :: (Request -> Request) -> m a -> m a Source #

Instances

Monad m => ServerMonad (ServerPartT m) Source # 
ServerMonad m => ServerMonad (ExceptT e m) Source # 

Methods

askRq :: ExceptT e m Request Source #

localRq :: (Request -> Request) -> ExceptT e m a -> ExceptT e m a Source #

(ServerMonad m, Monoid w) => ServerMonad (WriterT w m) Source # 

Methods

askRq :: WriterT w m Request Source #

localRq :: (Request -> Request) -> WriterT w m a -> WriterT w m a Source #

ServerMonad m => ServerMonad (StateT s m) Source # 

Methods

askRq :: StateT s m Request Source #

localRq :: (Request -> Request) -> StateT s m a -> StateT s m a Source #

(Error e, ServerMonad m) => ServerMonad (ErrorT e m) Source # 

Methods

askRq :: ErrorT e m Request Source #

localRq :: (Request -> Request) -> ErrorT e m a -> ErrorT e m a Source #

ServerMonad m => ServerMonad (StateT s m) Source # 

Methods

askRq :: StateT s m Request Source #

localRq :: (Request -> Request) -> StateT s m a -> StateT s m a Source #

(ServerMonad m, Monoid w) => ServerMonad (WriterT w m) Source # 

Methods

askRq :: WriterT w m Request Source #

localRq :: (Request -> Request) -> WriterT w m a -> WriterT w m a Source #

ServerMonad m => ServerMonad (ReaderT * r m) Source # 

Methods

askRq :: ReaderT * r m Request Source #

localRq :: (Request -> Request) -> ReaderT * r m a -> ReaderT * r m a Source #

(ServerMonad m, Monoid w) => ServerMonad (RWST r w s m) Source # 

Methods

askRq :: RWST r w s m Request Source #

localRq :: (Request -> Request) -> RWST r w s m a -> RWST r w s m a Source #

(ServerMonad m, Monoid w) => ServerMonad (RWST r w s m) Source # 

Methods

askRq :: RWST r w s m Request Source #

localRq :: (Request -> Request) -> RWST r w s m a -> RWST r w s m a Source #

mapServerPartT :: (UnWebT m a -> UnWebT n b) -> ServerPartT m a -> ServerPartT n b Source #

Apply a function to transform the inner monad of ServerPartT m.

Often used when transforming a monad with ServerPartT, since simpleHTTP requires a ServerPartT IO a. Refer to UnWebT for an explanation of the structure of the monad.

Here is an example. Suppose you want to embed an ErrorT into your ServerPartT to enable throwError and catchError in your Monad.

type MyServerPartT e m a = ServerPartT (ErrorT e m) a

Now suppose you want to pass MyServerPartT into a function that demands a ServerPartT IO a (e.g. simpleHTTP). You can provide the function:

  unpackErrorT :: (Monad m, Show e) => UnWebT (ErrorT e m) a -> UnWebT m a
  unpackErrorT et = do
     eitherV <- runErrorT et
     return $ case eitherV of
         Left err -> Just (Left $ toResponse $
                                  "Catastrophic failure " ++ show err
                          , filterFun $ \r -> r{rsCode = 500})
         Right x -> x

With unpackErrorT you can now call simpleHTTP. Just wrap your ServerPartT list.

 simpleHTTP nullConf $ mapServerPartT unpackErrorT (myPart `catchError` myHandler)

Or alternatively:

 simpleHTTP' unpackErrorT nullConf (myPart `catchError` myHandler)

Also see spUnwrapErrorT for a more sophisticated version of this function.

mapServerPartT' :: (Request -> UnWebT m a -> UnWebT n b) -> ServerPartT m a -> ServerPartT n b Source #

A variant of mapServerPartT where the first argument also takes a Request. Useful if you want to runServerPartT on a different ServerPartT inside your monad (see spUnwrapErrorT).

type UnWebT m a = m (Maybe (Either Response a, FilterFun Response)) Source #

UnWebT is almost exclusively used with mapServerPartT. If you are not using mapServerPartT then you do not need to wrap your head around this type. If you are -- the type is not as complex as it first appears.

It is worth discussing the unpacked structure of WebT a bit as it's exposed in mapServerPartT and mapWebT.

A fully unpacked WebT has a structure that looks like:

ununWebT $ WebT m a :: m (Maybe (Either Response a, FilterFun Response))

So, ignoring m, as it is just the containing Monad, the outermost layer is a Maybe. This is Nothing if mzero was called or Just (Either Response a, SetAppend (Endo Response)) if mzero wasn't called. Inside the Maybe, there is a pair. The second element of the pair is our filter function FilterFun Response. FilterFun Response is a type alias for SetAppend (Dual (Endo Response)). This is just a wrapper for a Response -> Response function with a particular Monoid behavior. The value

 Append (Dual (Endo f))

Causes f to be composed with the previous filter.

 Set (Dual (Endo f))

Causes f to not be composed with the previous filter.

Finally, the first element of the pair is either Left Response or Right a.

Another way of looking at all these pieces is from the behaviors they control. The Maybe controls the mzero behavior. Set (Endo f) comes from the setFilter behavior. Likewise, Append (Endo f) is from composeFilter. Left Response is what you get when you call finishWith and Right a is the normal exit.

An example case statement looks like:

 ex1 webt = do
   val <- ununWebT webt
   case val of
       Nothing -> Nothing  -- this is the interior value when mzero was used
       Just (Left r, f) -> Just (Left r, f) -- r is the value that was passed into "finishWith"
                                            -- f is our filter function
       Just (Right a, f) -> Just (Right a, f) -- a is our normal monadic value
                                              -- f is still our filter function

filterFun :: (a -> a) -> FilterFun a Source #

turn a function into a FilterFun. Primarily used with mapServerPartT

FilterMonad

class Monad m => FilterMonad a m | m -> a where Source #

A set of functions for manipulating filters.

ServerPartT implements FilterMonad Response so these methods are the fundamental ways of manipulating Response values.

Minimal complete definition

setFilter, composeFilter, getFilter

Methods

setFilter :: (a -> a) -> m () Source #

Ignores all previous alterations to your filter

As an example:

do
  composeFilter f
  setFilter g
  return "Hello World"

The setFilter g will cause the first composeFilter f to be ignored.

composeFilter :: (a -> a) -> m () Source #

Composes your filter function with the existing filter function.

getFilter :: m b -> m (b, a -> a) Source #

Retrieves the filter from the environment.

Instances

Monad m => FilterMonad Response (WebT m) Source # 
Monad m => FilterMonad Response (ServerPartT m) Source # 
FilterMonad a m => FilterMonad a (ExceptT e m) Source # 

Methods

setFilter :: (a -> a) -> ExceptT e m () Source #

composeFilter :: (a -> a) -> ExceptT e m () Source #

getFilter :: ExceptT e m b -> ExceptT e m (b, a -> a) Source #

(Error e, FilterMonad a m) => FilterMonad a (ErrorT e m) Source # 

Methods

setFilter :: (a -> a) -> ErrorT e m () Source #

composeFilter :: (a -> a) -> ErrorT e m () Source #

getFilter :: ErrorT e m b -> ErrorT e m (b, a -> a) Source #

(FilterMonad res m, Monoid w) => FilterMonad res (WriterT w m) Source # 

Methods

setFilter :: (res -> res) -> WriterT w m () Source #

composeFilter :: (res -> res) -> WriterT w m () Source #

getFilter :: WriterT w m b -> WriterT w m (b, res -> res) Source #

(FilterMonad res m, Monoid w) => FilterMonad res (WriterT w m) Source # 

Methods

setFilter :: (res -> res) -> WriterT w m () Source #

composeFilter :: (res -> res) -> WriterT w m () Source #

getFilter :: WriterT w m b -> WriterT w m (b, res -> res) Source #

FilterMonad res m => FilterMonad res (StateT s m) Source # 

Methods

setFilter :: (res -> res) -> StateT s m () Source #

composeFilter :: (res -> res) -> StateT s m () Source #

getFilter :: StateT s m b -> StateT s m (b, res -> res) Source #

FilterMonad res m => FilterMonad res (StateT s m) Source # 

Methods

setFilter :: (res -> res) -> StateT s m () Source #

composeFilter :: (res -> res) -> StateT s m () Source #

getFilter :: StateT s m b -> StateT s m (b, res -> res) Source #

Monad m => FilterMonad a (FilterT a m) Source # 

Methods

setFilter :: (a -> a) -> FilterT a m () Source #

composeFilter :: (a -> a) -> FilterT a m () Source #

getFilter :: FilterT a m b -> FilterT a m (b, a -> a) Source #

FilterMonad res m => FilterMonad res (ReaderT * r m) Source # 

Methods

setFilter :: (res -> res) -> ReaderT * r m () Source #

composeFilter :: (res -> res) -> ReaderT * r m () Source #

getFilter :: ReaderT * r m b -> ReaderT * r m (b, res -> res) Source #

(FilterMonad res m, Monoid w) => FilterMonad res (RWST r w s m) Source # 

Methods

setFilter :: (res -> res) -> RWST r w s m () Source #

composeFilter :: (res -> res) -> RWST r w s m () Source #

getFilter :: RWST r w s m b -> RWST r w s m (b, res -> res) Source #

(FilterMonad res m, Monoid w) => FilterMonad res (RWST r w s m) Source # 

Methods

setFilter :: (res -> res) -> RWST r w s m () Source #

composeFilter :: (res -> res) -> RWST r w s m () Source #

getFilter :: RWST r w s m b -> RWST r w s m (b, res -> res) Source #

ignoreFilters :: FilterMonad a m => m () Source #

Resets all your filters. An alias for setFilter id.

addHeaderM :: FilterMonad Response m => String -> String -> m () Source #

Add headers into the response. This method does not overwrite any existing header of the same name, hence the name addHeaderM. If you want to replace a header use setHeaderM.

getHeaderM :: ServerMonad m => String -> m (Maybe ByteString) Source #

Get a header out of the request.

setHeaderM :: FilterMonad Response m => String -> String -> m () Source #

Set a header into the response. This will replace an existing header of the same name. Use addHeaderM if you want to add more than one header of the same name.

neverExpires :: FilterMonad Response m => m () Source #

Set a far-future Expires header. Useful for static resources. If the browser has the resource cached, no extra request is spent.

WebMonad

class Monad m => WebMonad a m | m -> a where Source #

WebMonad provides a means to end the current computation and return a Response immediately. This provides an alternate escape route. In particular it has a monadic value of any type. And unless you call setFilter id first your response filters will be applied normally.

Extremely useful when you're deep inside a monad and decide that you want to return a completely different content type, since it doesn't force you to convert all your return types to Response early just to accommodate this.

see also: escape and escape'

Minimal complete definition

finishWith

Methods

finishWith Source #

Arguments

:: a

value to return (For ServerPart, a will always be the type Response)

-> m b 

Instances

Monad m => WebMonad Response (WebT m) Source # 

Methods

finishWith :: Response -> WebT m b Source #

Monad m => WebMonad Response (ServerPartT m) Source # 
WebMonad a m => WebMonad a (ExceptT e m) Source # 

Methods

finishWith :: a -> ExceptT e m b Source #

(Error e, WebMonad a m) => WebMonad a (ErrorT e m) Source # 

Methods

finishWith :: a -> ErrorT e m b Source #

(WebMonad a m, Monoid w) => WebMonad a (WriterT w m) Source # 

Methods

finishWith :: a -> WriterT w m b Source #

(WebMonad a m, Monoid w) => WebMonad a (WriterT w m) Source # 

Methods

finishWith :: a -> WriterT w m b Source #

WebMonad a m => WebMonad a (StateT s m) Source # 

Methods

finishWith :: a -> StateT s m b Source #

WebMonad a m => WebMonad a (StateT s m) Source # 

Methods

finishWith :: a -> StateT s m b Source #

WebMonad a m => WebMonad a (ReaderT * r m) Source # 

Methods

finishWith :: a -> ReaderT * r m b Source #

(WebMonad a m, Monoid w) => WebMonad a (RWST r w s m) Source # 

Methods

finishWith :: a -> RWST r w s m b Source #

(WebMonad a m, Monoid w) => WebMonad a (RWST r w s m) Source # 

Methods

finishWith :: a -> RWST r w s m b Source #

escape :: (WebMonad a m, FilterMonad a m) => m a -> m b Source #

Used to ignore all your filters and immediately end the computation. A combination of ignoreFilters and finishWith.

escape' :: (WebMonad a m, FilterMonad a m) => a -> m b Source #

An alternate form of escape that can be easily used within a do block.

MonadPlus helpers

require :: (MonadIO m, MonadPlus m) => IO (Maybe a) -> (a -> m r) -> m r Source #

Run an IO action and, if it returns Just, pass it to the second argument.

requireM :: (MonadTrans t, Monad m, MonadPlus (t m)) => m (Maybe a) -> (a -> t m r) -> t m r Source #

A variant of require that can run in any monad, not just IO.

escapeHTTP

escapeHTTP :: (ServerMonad m, MonadIO m) => (TimeoutIO -> IO ()) -> m a Source #