Hello,
I am a beginner with Haskell and the last few days I am troubled on how to form a stack of Monad Transformers.
The following example demonstrates the use of multiple State monads without the use of Monad Transformers:
data Item = Item { rCounter :: Int }
increaseCounter :: State Item ()
increaseCounter = do
val <- gets rCounter
modify (\i -> i { rCounter = val + 1 })
data ItemManager = ItemManager { rItems :: [Item] }
addItem :: Item -> State ItemManager ()
addItem item = do
items <- gets rItems
modify (\mgr -> mgr { rItems = items ++ [item] })
increaseCounterInItems :: State ItemManager ()
increaseCounterInItems = do
items <- gets rItems
let items' = map (execState increaseCounter) items
modify (\mgr -> mgr { rItems = items' })
main :: IO ()
main = $ do
let itemMgrState = do
addItem $ Item 0
addItem $ Item 10
increaseCounterInItems
let itemMgr = execState itemMgrState $ ItemManager []
let items = rItems itemMgr
putStrLn rCounter (items !! 0) -- prints 1
putStrLn rCounter (items !! 1) -- prints 11
In the above implementation calls execState, inside functions of ItemManager, for updating Items.
I have read about MonadTransformers and that they give you the ability to use monads inside the context of another monad.
So I would like to use StateT in signatures of ItemManager's functions and avoid calling execState, something like this:
increaseCounterInltems :: StateT ItemManager (State Item) ()
But I cannot find a way to implement the above function. The root cause of the difficulty seems to be that ItemManager contains multiple Items.
The Monad Transformer stack contains a single State Item. So it seems to me that I am following the wrong approach.
How could I use Monad Transformers in order to avoid calling execState for modifying Items in ItemManager?
Thanks in advance,
Leonidas