Timeouts in Haskell
Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Haskell can be achieved using the timeout function from the System.Timeout module.
import Control.Concurrent (threadDelay)
import System.Timeout (timeout)
import Control.Monad (void)
main :: IO ()
main = do
-- For our example, suppose we're executing an external
-- call that returns its result after 2s.
let slowOperation = do
threadDelay (2 * 1000000) -- 2 seconds
return "result 1"
-- Here we implement a timeout using the `timeout` function.
-- It will wait for 1 second for the result.
result1 <- timeout (1 * 1000000) slowOperation
case result1 of
Just res -> putStrLn res
Nothing -> putStrLn "timeout 1"
-- If we allow a longer timeout of 3s, then the operation
-- will succeed and we'll print the result.
let anotherSlowOperation = do
threadDelay (2 * 1000000) -- 2 seconds
return "result 2"
result2 <- timeout (3 * 1000000) anotherSlowOperation
case result2 of
Just res -> putStrLn res
Nothing -> putStrLn "timeout 2"In this Haskell version:
We use
threadDelayto simulate a slow operation. It takes microseconds as an argument, so we multiply seconds by 1,000,000.The
timeoutfunction fromSystem.Timeoutis used to implement the timeout mechanism. It takes a time in microseconds and an IO action, and returnsNothingif the action doesn’t complete within the specified time, orJust resultif it does.We use pattern matching with
caseexpressions to handle the results oftimeout.Unlike in the original example, we don’t need to use channels or select statements, as Haskell’s
timeoutfunction provides a more straightforward way to implement timeouts.
Running this program shows the first operation timing out and the second succeeding:
$ runhaskell timeouts.hs
timeout 1
result 2This example demonstrates how to implement timeouts in Haskell, which is useful for bounding the execution time of operations that might take too long to complete.