I have written a simple WAI application, which uses a ReaderT to allow access to the request like so:
import qualified Network.Wai as W
handle :: (Resource a) => a -> ReaderT W.Request IO W.Response
where handle
is the function that does the bulk of the processing. I then call it in my application:
app :: W.Application
app = runReaderT (handle a) -- simplified; i don't think the value of a matters
main :: IO ()
main = run 3000 app
but runhaskell main.hs
gives me the following:
Couldn't match expected type `Control.Monad.Trans.Resource.ResourceT
IO'
with actual type `IO'
Expected type: ReaderT
W.Request (Control.Monad.Trans.Resource.ResourceT IO) W.Response
Actual type: ServerMonad W.Response
In the return type of a call of `handle'
In the first argument of `runReaderT', namely
`(handle a)'
which confuses me for two reasons:
- I don't have any idea why it's expecting that type
- Calling
resp <- runReaderT (handle a) defaultRequest
works in GHCI!
Why is this happening?
The type
Application
is defined as:(The reason for ResourceT is so that you can allocate scarce resources and use them when sending a streaming response. This would be relevant for sending back a response based on a large database query. But that's not directly relevant for your question.)
Your
runReaderT (reader a)
has typeRequest -> IO Response
. In order to get it to return the response inResourceT IO
, there seem to be two options:app
:app = lift . runReaderT (reader a)
. (lift
is defined inControl.Monad.Trans.Class
.)hanlde
tohandle :: (Resource a) => a -> ReaderT W.Request (ResourceT IO) W.Response
.The first approach makes sense if you might ever need to perform a resource-sensitive operation, whereas the second will likely be an easier change.