
Hello: I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ. I created a Monad transformer stack (ReaderT AppConfig IO a) to carry around my application configuration and AMQP connection handle (MVar Connection within AppConfig), but I am having difficulty determining how to integrate it with my Warp application. The function which is responsible for accepting Requests and returning Responses (app :: Application) needs to call functions which require AppConfig. For example: (sendToRabbitMQ :: RPCRequest -> MyApp ByteString) is a blocking call which requires the AMQP connection handle found within AppConfig, which is why it returns a MyApp ByteString as opposed to a IO ByteString. If I want to call `sendToRabbitMQ' from `app', then the type of `app' needs to change from Application to something else, but I am not sure what that should be. What's the best way to proceed? -- Alex

Typically it would look something like this:
myApp :: AppConfig -> Application
main = do
appConfig <- getAppConfig
run 3000 $ myApp appConfig
Within myApp, you can now access the AppConfig value and use runReaderT to
unwrap your MyApp transformer.
On Sat, May 16, 2015 at 3:03 PM Alex
Hello:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I created a Monad transformer stack (ReaderT AppConfig IO a) to carry around my application configuration and AMQP connection handle (MVar Connection within AppConfig), but I am having difficulty determining how to integrate it with my Warp application.
The function which is responsible for accepting Requests and returning Responses (app :: Application) needs to call functions which require AppConfig. For example: (sendToRabbitMQ :: RPCRequest -> MyApp ByteString) is a blocking call which requires the AMQP connection handle found within AppConfig, which is why it returns a MyApp ByteString as opposed to a IO ByteString. If I want to call `sendToRabbitMQ' from `app', then the type of `app' needs to change from Application to something else, but I am not sure what that should be.
What's the best way to proceed?
-- Alex _______________________________________________ web-devel mailing list web-devel@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/web-devel

On Sat, 16 May 2015 18:30:31 +0000
Michael Snoyman
Typically it would look something like this:
myApp :: AppConfig -> Application
main = do appConfig <- getAppConfig run 3000 $ myApp appConfig
Within myApp, you can now access the AppConfig value and use runReaderT to unwrap your MyApp transformer.
Is a consequence of this design that I have to use runReaderT every time I want to use a function of the type (Foo -> MyApp Bar) from within myApp? Is it better/easier to simply rewrite the all functions myApp calls so that they accept an AppConfig parameter instead of returning a MyApp Bar? -- Alex

On Sat, May 16, 2015 at 10:05 PM Alex
On Sat, 16 May 2015 18:30:31 +0000 Michael Snoyman
wrote: Typically it would look something like this:
myApp :: AppConfig -> Application
main = do appConfig <- getAppConfig run 3000 $ myApp appConfig
Within myApp, you can now access the AppConfig value and use runReaderT to unwrap your MyApp transformer.
Is a consequence of this design that I have to use runReaderT every time I want to use a function of the type (Foo -> MyApp Bar) from within myApp? Is it better/easier to simply rewrite the all functions myApp calls so that they accept an AppConfig parameter instead of returning a MyApp Bar?
-- Alex
That's one approach. You can also do something like: myApp appConfig req respond = flip runReaderT appConfig $ do someFunc ... someFunc :: MyApp ()
participants (2)
-
Alex
-
Michael Snoyman