Search code examples
haskellstm

Modify and print state using STM


I'm able to initialise a state using STM and print it out:

module Main where

import Control.Concurrent.STM

data State = State {name :: String} deriving (Show)

type MyAppState = TVar [State]

initState :: STM MyAppState
initState = newTVar [State "hi"]

main :: IO ()
main =  
  do 
    state <- atomically initState
    stateToPrint <- readTVarIO state
    putStrLn (show stateToPrint)

I have tried to create function to update the state:

updateState :: String -> State -> State 
updateState newName s = State newName : s

But I'm not sure how to place it in the main 'do' block without the compiler throwing an error since it expects a type of State but it is passed a MyAppState.


Solution

  • You can use writeTVar :: TVar a -> a -> STM ():

    main :: IO ()
    main = do 
        state <- atomically initState
        stateToPrint <- readTVarIO state
        putStrLn (show stateToPrint)
        atomically (readTVar state >>= writeTVar state . fmap (updateState "foo"))

    We here thus read the content of the state, then we pass it through an fmap updateState to update the elements in the list, and then we write that to the state var.

    That being said, it might be useful to look for a state monad transformer, like in the Control.Monad.Trans.State module of the transformers package.

    Note that your updateState function is not properly defined, you perhaps want to define this like:

    updateState :: String -> State -> State 
    updateState newName (State s) = State (newName ++ s)