this sort of a follow-up question to my previous one: State and IO Monads
My goal is to create a simple text-editor for files. I already have an Editor
component that nicely encapsulates all editing actions on an underlying data structure.
Thanks to the answers to my previous question, I was able to refactor my program so that I now have a nice monad transformer stack:
type Session = StateT AppState (StateT Editor IO)
AppState
holds the global state of the application (currently open file, etc...), while Editor
represents the inner state of the editing-component of the app (where the caret is at, etc...). I have a function that is the main driver of the application:
eventLoop :: Session ()
So far so good, however now I don't know how I can actually kick-start my transformer stack from my main
function? Main has to return something in the IO
monad which is at the very base of my stack. My guess is that I have to initialize my AppState
and then do something like:
main = do
let initialAppState = ...
return $ runStateT eventLoop initialAppState
But where do I initialize my Editor
now?
The main thing confusing me is that before the refactoring, Editor
was simply a member of AppState
:
data AppState = { editor :: Editor , ... }
but now it has moved out of AppState
and become somewhat of a sibling on the transformer stack. Shouldn't Editor
still be part of AppState
because modifying it means modifying the overall state?
How do I properly initialize my Session
with both AppState
and Editor
and then run it from my main
?