I'm working with dbus in haskell, and I'm having difficulties figuring out how to export dbus methods that perform stateful operations. Below is a fully fleshed out example to illustrate where I'm stuck.
Let's say you're writing a counter service with dbus. When the service starts, the counter is initially at 0. The service defines a dbus API that exposes a count
method, which returns the current value of the counter, and an update
method, which increments that counter, and returns the new value.
Here's a pseudocodey implementation of the behavior I just described, using a message-passing-style of communication:
-- | Updates the given integer.
update :: Int -> Int
update = (+1)
-- | main function with message-passing-style communication
mainLoop :: Int -> IO Int
mainLoop state = do
case receiveMessage of
"update" -> do -- increment / update counter
sendReply $ update state
mainLoop $ update state -- recurse
"count" -> do -- return counter value
sendReply state
mainLoop state
"stop" -> do -- stop the counting service
exitSuccess
main :: IO ()
main = do
mainLoop 0
However, dbus uses method-calls, not message passing. So, I need to be able to export a count
and update
method that behaves the same way as in my message-passing example.
The stub we'll work with is something like this:
-- | Updates the given integer.
update :: Int -> Int
update = (+1)
main :: IO ()
main = do
let initialState = 0
dbus <- connectSession
export dbus "/org/counter/CounterService"
[ autoMethod "org.counter.CounterService" "update" ({-- call update? --})
, autoMethod "org.counter.CounterService" "count" ({-- return state? --}) ]
And here lies my question: How should I encode the missing {-- call update? --}
and {-- return state? --}
functions?
I know I can use an MVar
to create global mutable state, and then just make the functions read from that, but I want to avoid mutability as much as possible here. I think I can do this with the Reader/State monad somehow, maybe by sneaking a get
/ask
into the functions, but I don't know how to handle the types with respect to DBus.