Context in F#

Here’s the translation of the Go code to F# 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 Async for controlling cancellation. Async in F# provides a way to work with asynchronous computations and allows for cancellation.

open System
open System.Net
open System.Threading
open System.Threading.Tasks

let hello (ctx: HttpListenerContext) (cts: CancellationTokenSource) =
    async {
        // An Async computation is created for each request
        printfn "server: hello handler started"
        
        try
            // Simulate some work the server is doing
            do! Task.Delay(TimeSpan.FromSeconds(10.0), cts.Token) |> Async.AwaitTask
            
            use writer = new System.IO.StreamWriter(ctx.Response.OutputStream)
            do! writer.WriteAsync("hello\n") |> Async.AwaitTask
        with
        | :? OperationCanceledException as ex ->
            // If the operation was cancelled, we can handle it here
            printfn "server: %s" ex.Message
            ctx.Response.StatusCode <- 500
            use writer = new System.IO.StreamWriter(ctx.Response.OutputStream)
            do! writer.WriteAsync(ex.Message) |> Async.AwaitTask
        
        printfn "server: hello handler ended"
    }

let main() =
    let listener = new HttpListener()
    listener.Prefixes.Add("http://localhost:8090/")
    listener.Start()
    printfn "Listening on http://localhost:8090/"

    while true do
        let ctx = listener.GetContext()
        let cts = new CancellationTokenSource()
        
        // Handle each request in a separate async computation
        Async.Start(hello ctx cts, cts.Token)

[<EntryPoint>]
let entryPoint _ =
    main()
    0

To run the server:

$ dotnet fsi server.fsx &

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

$ curl http://localhost:8090/hello
server: hello handler started
^C
server: The operation was canceled.
server: hello handler ended

In this F# version:

  1. We use HttpListener to set up a simple HTTP server.
  2. The hello function is an asynchronous computation that handles each request.
  3. We use Task.Delay to simulate work, which can be cancelled.
  4. Cancellation is handled using a CancellationTokenSource.
  5. If cancellation occurs, we catch the OperationCanceledException and respond with an error.

This example demonstrates how to use F#’s asynchronous programming model to handle cancellation in a way similar to Go’s context package.