Context in Haskell

Here’s the translation of the Go code to Haskell, along with explanations in Markdown format suitable for Hugo:

In this example, we’ll look at setting up a simple HTTP server. HTTP servers are useful for demonstrating the usage of cancellation control. In Haskell, we can use the async library for handling cancellation and timeouts.

{-# LANGUAGE OverloadedStrings #-}

import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (race)
import Control.Monad (void)
import Network.Wai (Application, responseLBS)
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (status200, status500)
import qualified Data.ByteString.Lazy.Char8 as LBS

hello :: Application
hello req respond = do
    putStrLn "server: hello handler started"
    result <- race (threadDelay 10000000) (return "hello\n")
    case result of
        Left _ -> 
            respond $ responseLBS status200 [] "hello\n"
        Right _ -> do
            putStrLn "server: request cancelled"
            respond $ responseLBS status500 [] "Internal Server Error"
    putStrLn "server: hello handler ended"

main :: IO ()
main = do
    putStrLn "Starting server on port 8090..."
    run 8090 hello

In this Haskell version:

  1. We use the wai and warp libraries to create a simple HTTP server.

  2. The hello function is our request handler. It simulates work by waiting for 10 seconds before responding.

  3. We use the race function from the async library to implement a timeout. This is similar to the select statement in the original Go code.

  4. If the delay completes before cancellation, we send a “hello” response. If cancellation occurs first, we send an error response.

  5. In the main function, we start the server on port 8090.

To run the server:

$ runhaskell context.hs &

To simulate a client request to /hello, hitting Ctrl+C shortly after starting to signal cancellation:

$ curl localhost:8090/hello
server: hello handler started
^C
server: request cancelled
server: hello handler ended

Note that Haskell doesn’t have a built-in concept directly equivalent to Go’s context.Context. The async library provides similar functionality for handling cancellation and timeouts in concurrent operations.