
On 29 Jan 2008, at 9:44 PM, Adam Smyczek wrote:
Hi,
My application has to manage a data set. I assume the state monad is designed for this. The state changes in functions that: a. perform IO actions and b. return execution status and execution trace (right now I'm using WriteT for this).
Is the best solution: 1. to build a monad stack (for example State -> Writer -> IO) or 2. to use IORef for the data set or 3. something else?
Are monad stacks with 3 and more monads common?
I'd say they're fairly common, yes; at least, they don't jump out at me as bad style (especially when the monads are fairly orthogonal, as here).
How could an example implementation look like?
newtype Program alpha = Program { runProgram :: StateT Config (WriterT [String] IO) alpha } deriving (Functor, Monad, MonadWriter, MonadState)
What I have for now is:
-- Status data Status = OK | FAILED deriving (Show, Read, Enum)
-- Example data set manages by state type Config = [String]
-- WriterT transformer type OutputWriter = WriterT [String] IO Status
-- example execute function execute :: [String] -> OutputWriter
execute :: [String] -> Program Status
execute fs = do rs <- liftIO loadData fs tell $ map show rs return OK
-- run it inside e.g. main (s, os) <- runWriterT $ execute files
(s', (s, os)) <- runWriterT (runStateT (runProgram $ execute files) inputstate) It's a bit tricky, since you have to write it inside-out, but it should only type check if you've got it right :)
How do I bring a state into this, for example for: execute fs = do ?? conf <- get ?? -- get Config from state
Right.
rs <- liftIO loadData conf fs ?? set conf ?? -- change Config and set to state
Right.
tell "new state:"
Right.
tell $ show conf return OK
Do I have to use
Depends on what you mean by `have to'. If you don't want to thread the state yourself, and you don't want to use an IORef, you'll need some implementation of a state monad. That will have to be in the form of a monad transformer applied to IO, so the easy answer is `yes'.
and how do I use StateT in this context: data DataState = StateT Config OutputWriter ??
This is parenthesized wrong; the output type goes outside the parentheses around WriterT: StateT Config (WriterT [String] IO) Status not StateT Config (WriterT [String] IO Status)
and how do I run it runStateT . runWriterT?
Other way 'round, as above. HTH jcc