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
= main do
newTVarinitializes a new variable. Here we initialize two variables,
a = 3and
b = 5.
<- atomically (newTVar 3) a <- atomically (newTVar 5) b let = printVars label do
readTVarreturns the variable’s current value.
printVars function reads and then prints the values of
b. We will use it repeatedly to watch how these two variables change as the program runs.
<- atomically (readTVar a) x1 <- atomically (readTVar b) x2 putStrLn ("a = " ++ show x1 ++ ", b = " ++ show x2 ++ " (" ++ label ++ ")") "initial values" printVars
writeTVarassigns a new value to a variable. Here we reassign
awith a new value of
7) atomically (writeTVar a "changed a to 7" printVars
modifyTVar'applies a function to a variable’s value. Here we apply the function
(* 2)to double the value of
* 2)) atomically (modifyTVar' b ("doubled b" printVars
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 = atomically (modifyTVar' ref (+ 1)) increment ref = swap ref1 ref2 $ atomically do <- readTVar ref1 x1 <- readTVar ref2 x2 writeTVar ref1 x2 writeTVar ref2 x1
a once, then increment
b five times in a for loop.
increment a1..5] $ \_ -> for_ [ increment b"incremented" printVars
And finally, we’ll swap the values of
swap a b"swapped" printVars
When we run the program, we can see how the values of
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)