Reputation: 2603
I'm trying to get more familiar with Haskell by developing web-app-ish services.
Say I'm developing a web-server and I want to keep persistent state between requests; a counter, for instance. What is the Haskell way of doing things?
I came across this discussion on my Google search. The proposed solution looks like a good example of what not to do.
One idea I had was having the request handler take in an MVar:
requestHandler :: MVar State -> IO (Maybe Response)
When registering the handler, it could be curried with an MVar created in main.
There must be a better way. I can't help but think I'm approaching this problem in a non-functional way.
Thanks!
Upvotes: 7
Views: 649
Reputation: 166
If you like persistence and TVars, you can use DBRefs, that have the same semantics and the same usage patterns as TVars. You must define a unique key for the state and you have automatic file persistence. For database persistence it is necessary to define an IResource instance.
The state will have a unique counter for each session:
import Data.Map as M
import Data.TCache
import Data.TCache.DefaultPersistence
type Counter= Int
type SessionId :: String
data State= State SessionId Counter deriving (Read, Show, Typeable)
instance Indexable State where
key (State k _)= k
requestHandler :: Request -> DBRef State -> IO (Maybe Response)
Upvotes: 1
Reputation: 692
You probably want acid-state, which gives you that exactly: persistent state for Haskell data types. The documentation I linked even starts out with a request counter, just like you asked for.
Note that MVars are not persistent; the counter would get reset when the server is restarted. If that's actually the behavior you want I suggest you use a TVar instead; that way you can update the counter atomically without locks or the risk of deadlocks that go with them.
Upvotes: 4