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 TVar
s:
=
main do
newTVar
initializes a new variable. Here we initialize two variables,a = 3
andb = 5
.
<- atomically (newTVar 3)
a <- atomically (newTVar 5)
b
let
=
printVars label do
readTVar
returns 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.
<- atomically (readTVar a)
x1 <- atomically (readTVar b)
x2 putStrLn ("a = " ++ show x1 ++ ", b = " ++ show x2
++ " (" ++ label ++ ")")
"initial values" printVars
writeTVar
assigns a new value to a variable. Here we reassigna
with a new value of7
.
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 ofb
.
* 2))
atomically (modifyTVar' b ("doubled b" printVars
Mutable references can be passed as arguments to functions. Here we define two functions:
increment
increases a variable’s value by one;swap
interchanges 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
We increment 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 a
and b
.
swap a b"swapped" printVars
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