🎓 A1Learner
🔍
0 of 47 lessons completed

Haskell STM Transactions

An STM transaction is a group of reads and writes that succeeds as one step. It runs inside atomically and touches only TVars.

One transaction reads two boxes and adds them

Start with 20 and 22. Read both inside one transaction and add them.

import Control.Concurrent.STM

main :: IO ()
main = do
  a <- newTVarIO (20 :: Int)
  b <- newTVarIO (22 :: Int)
  total <- atomically $ do
    x <- readTVar a
    y <- readTVar b
    return (x + y)
  print total

One transaction changes a value only when it can afford it

Start with 100. Take 30 inside one transaction only when the balance is at least 30.

import Control.Concurrent.STM
import Control.Monad (when)

main :: IO ()
main = do
  t <- newTVarIO (100 :: Int)
  atomically $ do
    v <- readTVar t
    when (v >= 30) (writeTVar t (v - 30))
  result <- readTVarIO t
  print result

One transaction moves a value between boxes

Start with 30 in the first box and 0 in the second. Move the whole value across in one transaction.

import Control.Concurrent.STM

main :: IO ()
main = do
  a <- newTVarIO (30 :: Int)
  b <- newTVarIO (0 :: Int)
  atomically $ do
    v <- readTVar a
    writeTVar b v
    writeTVar a 0
  x <- readTVarIO a
  y <- readTVarIO b
  print (x, y)

Example

import Control.Concurrent.STM

main :: IO ()
main = do
  stock <- newTVarIO (50 :: Int)
  sold <- newTVarIO (0 :: Int)
  atomically $ do
    s <- readTVar stock
    writeTVar stock (s - 8)
    modifyTVar' sold (+ 8)
  x <- readTVarIO stock
  y <- readTVarIO sold
  print (x, y)

Key points

  • Transaction: a group of reads and writes that succeeds as one step.
  • Atomically: atomically runs a transaction and returns its result.
  • ReadTVar: readTVar reads a TVar inside a transaction.
  • WriteTVar: writeTVar sets a TVar inside a transaction.
  • ModifyTVar': modifyTVar' changes a TVar inside a transaction by applying a function.

In this example, stock starts at 50 and sold starts at 0. One transaction takes 8 from stock and adds 8 to sold. The main thread reads both back and prints 42 and 8.

Note

a transaction cannot do ordinary input and output. It touches TVars only.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Haskell Playground

Exercise

What can an STM transaction touch?