Timers in Haskell
Our first example demonstrates the use of timers in Haskell. We often want to execute code at some point in the future, or repeatedly at some interval. Haskell’s threadDelay
function and the async
library can help us achieve these tasks easily.
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (async, cancel)
import Control.Monad (void)
import System.IO (hFlush, stdout)
main :: IO ()
main = do
-- Timers represent a single event in the future. You
-- tell the timer how long you want to wait, and it
-- will execute after that time. This timer will wait 2 seconds.
putStrLn "Starting Timer 1"
threadDelay (2 * 1000000) -- 2 seconds
putStrLn "Timer 1 fired"
-- If you just wanted to wait, you could have used
-- threadDelay directly. One reason to use async is
-- that you can cancel the timer before it fires.
-- Here's an example of that.
putStrLn "Starting Timer 2"
timer2 <- async $ do
threadDelay 1000000 -- 1 second
putStrLn "Timer 2 fired"
cancel timer2
putStrLn "Timer 2 stopped"
-- Give timer2 enough time to fire, if it ever
-- was going to, to show it is in fact stopped.
threadDelay (2 * 1000000) -- 2 seconds
-- Ensure all output is flushed
hFlush stdout
To run the program, save it as timers.hs
and use runhaskell
:
$ runhaskell timers.hs
Starting Timer 1
Timer 1 fired
Starting Timer 2
Timer 2 stopped
The first timer will fire ~2s after we start the program, but the second should be stopped before it has a chance to fire.
In this Haskell version:
We use
threadDelay
to create delays. The argument tothreadDelay
is in microseconds, so we multiply by 1,000,000 to get seconds.Instead of channels, we use the
async
library to create asynchronous actions that can be cancelled.The
cancel
function is used to stop the second timer before it fires.We use
putStrLn
for output andhFlush stdout
to ensure all output is displayed immediately.
This example demonstrates basic timer functionality in Haskell, including creating timed events and cancelling them before they occur.