[Haskell-cafe] State separation/combination pattern question
Reto Kramer
ml at retokramer.net
Fri Dec 22 01:11:22 EST 2006
I'm looking for a pattern to use for "state separation" in my
application.
I need to write two "stateful libraries". One is a partitioned in-
memory store, the other a disk based store with an in-memory cache
fronting it. Both store modules need the IO and State monad.
My aim is to write the libraries independently from one another in
such a way that they are not aware of the context they will be used
in. Both stores are called from a breadth first search loop.
The example below extracts the essence of my current approach. foo is
function in one of the store modules, bar is from the other type of
store. Both manipulate their type of state (StateA, StateB). They
extract their slice of the "global" application level state
(AppStateRec). What I don't like is that the code in foo and bar know
about the AppStateRec and that they need to get the "a", or "b" slot
respectively. The store modules should not have such coupling with
their client code.
I've tried to thread the two states (StateA and StateB) using a chain
of StateT ... StateT ..., but couldn't really make that work. It
seems rather arbitrary in this case which state to make the inner/
outer one and depending on this ordering the "lifts" have to go with
one or the other set of store calls.
What I'm really looking for is not so much the chaining of StateT
compositions, but rather the isolation of StateA from StateB while
they both flow from the search loop into the respective library calls
(foo, bar) transparently to the application programmer. I'm hoping
there's a way to have the loop be in a State monad whose content is
the sum of the two states that are needed for the foo and bar call
made to the stores from inside the loop. The calls sites for foo and
bar should then extract the right component of the global state and
thread only that state through into the modules. Sounds like magic,
but how close can I get?
I've been unable to find a pattern on the WIKI or the web that refers
to this type of "state composition" (or I may not have recognized the
match). I trust many of you have run into this and there's an
obvious and straight forward best way to address this type of state
handling.
Thanks,
- Reto
--------------------------
-- ghci -fglasgow-exts ...
--
type StateA = [Integer]
type StateB = [Integer]
data AppStateRec = AppStateRec { a :: StateA, b :: StateB } deriving
Show
foo :: MonadState AppStateRec m => m ()
foo = do st <- get
put $ st { a = 1:(a st) }
bar :: MonadState AppStateRec m => m ()
bar = do st <- get
put $ st { b = 2:(b st) }
type Eval a = StateT AppStateRec Identity a
exec :: Eval ()
exec = do foo
bar
foo
foo
bar
go = runIdentity $ runStateT exec AppStateRec { a = [], b = [] }
Prints: ((),AppStateRec {a = [1,1,1], b = [2,2]})
More information about the Haskell-Cafe
mailing list