A TVar is a variable whose value can be changed. Reading a TVar gets its current value, and writing a TVar assigns it a new value.
TVar comes from the stm library. The ‘T’ in both ‘STM’ and ‘TVar’ stands for ‘transactional’, which refers to some impressive thread-safety properties of these variables. But this won’t matter until we fork some threads later on.
import Control.Monad.STM
import Control.Concurrent.STM.TVar
import Data.Foldable (for_)There are four important functions to remember when working with TVars:
main =
donewTVarinitializes a new variable. Here we initialize two variables,a = 3andb = 5.
a <- atomically (newTVar 3)
b <- atomically (newTVar 5)
let
printVars label =
doreadTVarreturns the variable’s current value.
The printVars function reads and then prints the values of a and b. We will use it repeatedly to watch how these two variables change as the program runs.
x1 <- atomically (readTVar a)
x2 <- atomically (readTVar b)
putStrLn ("a = " ++ show x1 ++ ", b = " ++ show x2
++ " (" ++ label ++ ")")
printVars "initial values"writeTVarassigns a new value to a variable. Here we reassignawith a new value of7.
atomically (writeTVar a 7)
printVars "changed a to 7"modifyTVar'applies a function to a variable’s value. Here we apply the function(* 2)to double the value ofb.
atomically (modifyTVar' b (* 2))
printVars "doubled b"Mutable references can be passed as arguments to functions. Here we define two functions:
incrementincreases a variable’s value by one;swapinterchanges the values of two variables.
let
increment ref = atomically (modifyTVar' ref (+ 1))
swap ref1 ref2 =
atomically $
do
x1 <- readTVar ref1
x2 <- readTVar ref2
writeTVar ref1 x2
writeTVar ref2 x1We increment a once, then increment b five times in a for loop.
increment a
for_ [1..5] $ \_ ->
increment b
printVars "incremented"And finally, we’ll swap the values of a and b.
swap a b
printVars "swapped"When we run the program, we can see how the values of a and b evolve throughout the program’s execution.
$ runhaskell mutable-references.hs
a = 3, b = 5 (initial values)
a = 7, b = 5 (changed a to 7)
a = 7, b = 10 (doubled b)
a = 8, b = 15 (incremented)
a = 15, b = 8 (swapped)Next: Threads

