i'm implementing simple http server and i want my responses depend on some global state. For example if i get request 'get_settings' from the same client for the first time i will send large settings json, and for the second time i will just send 'Not-modified' http response.
Something like that
import Network.Simple.TCP
main = withSocketsDo $ do
let settings_state = 0 -- flag for settings response
serve (Host "127.0.0.1") "23980" $ \(conn_sock, remote_addr) -> do
putStrLn $ "TCP connection established from " ++ show remote_addr
(Just inp) <- recv conn_sock 1024
send conn_sock (process inp settings_state)
process :: B.ByteString -> Int -> B.ByteString
process inp flag
| flag == 0 = ... -- return full response and change global flag
| otherwise = ... -- return 'Not-modified'
And the question is how can i implement it? And i would like to do it as simple as possible, manually, without any Monad Transformers and so on. Let the code be ugly, but simple. Thanks
Since changing the flag clearly has some side effects, the result of
process
will be inIO
:Since you don't want to use any kind of monad transformer, you need to exchange the
Int
with some mutable reference. Yes, you've read correctly: There are several types that are mutable, such asIORef
,MVar
,TVar
,MVector
,STRef
…. To stay simple, lets stick toIORef
.Note that you didn't provide any logic for the flag, so I simply increased the value, but you probably want to do something else (or change the flag to
IORef Bool
). Note that you also want to useatomicModifyIORef'
if you want to use theIORef
safely in a multithreaded program:Either way, you need to create the
IORef
withnewIORef value
, so your code snippets becomes something like