🎓 A1Learner
🔍
0 of 50 lessons completed

Haskell IORef State

Haskell IORef state is a changeable box that lives inside IO. It lets an IO program keep a value that later steps can read and update.

Write replaces the boxed value

The box starts at 10. Writing 20 replaces that value.

import Data.IORef
main :: IO ()
main = do
  ref <- newIORef 10
  a <- readIORef ref
  writeIORef ref 20
  b <- readIORef ref
  print (a, b)

Modify changes the boxed value

The box starts at 7. Adding 3 and then doubling gives 20.

import Data.IORef
main :: IO ()
main = do
  ref <- newIORef 7
  modifyIORef ref (+3)
  modifyIORef ref (*2)
  v <- readIORef ref
  print v

A helper can bump a shared box

One helper adds 1 to any box it is given. Calling it twice leaves 2 in the box.

import Data.IORef
bump :: IORef Int -> IO ()
bump r = modifyIORef r (+1)
main :: IO ()
main = do
  ref <- newIORef 0
  bump ref
  bump ref
  v <- readIORef ref
  print v

Example

import Control.Monad (forM_)
import Data.IORef
main :: IO ()
main = do
  count <- newIORef 0
  total <- newIORef 0
  forM_ [4,5,6] (\x -> modifyIORef count (+1) >> modifyIORef total (+x))
  c <- readIORef count
  t <- readIORef total
  print (c, t)

Key points

  • IORef: an IORef is a box that holds one value a program can change.
  • New: newIORef makes a box holding a starting value.
  • Read: readIORef reads the value currently in the box.
  • Write: writeIORef replaces the value in the box.
  • Modify: modifyIORef changes the value by applying a function to it.

In this example, the program makes two boxes for a count and a total. It walks three numbers and bumps the count once and adds each number to the total. It prints the final count and total together.

Note

an IORef only works inside IO, so pure code cannot read or change it.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Haskell Playground

Exercise

What is the difference between writeIORef and modifyIORef?