I want to write a web server which stores its state in a State
monad with wai
/warp
. Something like this:
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Warp
import Network.HTTP.Types
import Control.Monad.State
import Data.ByteString.Lazy.Char8
main = run 3000 app
text x = responseLBS
status200
[("Content-Type", "text/plain")]
x
app req = return $ text "Hello World"
app1 req = modify (+1) >>= return . text . pack . show
-- main1 = runStateT (run 3000 app1) 0
The commented line doesn't work, of course. The intent is to store a counter in a state monad and display its increasing value on every request.
Also, how do I get thread safety? Does warp run my middleware sequentially or in parallel?
What options are available for the state - is there anything at all besides IORef
I can use in this scenario?
I understand that State gives safety but it seems wai doesn't allow State.
I only need a dead-simple single-threaded RPC I can call from somewhere else. Haxr
package requires a separate web server which is an overkill. See Calling Haskell from Node.JS - it didn't have any suggestions so I wrote a simple server using Wai/Warp and Aeson. But it seems that WAI was designed to support concurrent implementatons so it complicates things.
If your interaction with the state can be expressed with a single call to
atomicModifyIORef
, you can use that, and you don't need to explicitly serialise access to the state.If your interaction is more complex and you need to enforce full serialisation of requests, you can use an
MVar
in conjunction withStateT
.