Skip to content
Async Workflows
step 1/5

Reading — step 1 of 5

Learn

~1 min readOption/Result and Async

F# has its own async model — older than C#'s but with similar semantics. The async { ... } block builds a workflow; you run it with Async.RunSynchronously or Async.Start.

let fetchUserAge id : Async<int> = async {
    let! user = db.GetUser(id)              // let! awaits an Async<T>
    let! profile = api.GetProfile(user)
    return profile.Age
}

// Run it:
let age = fetchUserAge 42 |> Async.RunSynchronously

Key points:

  • let! awaits an Async<T> and binds the result
  • do! awaits an Async<unit> (no value)
  • return exits the workflow with a value
  • The workflow itself is a value (not started until you tell it to)

Parallelism with Async.Parallel:

let workflows = [
    fetchUser 1
    fetchUser 2
    fetchUser 3
]
let allResults = workflows |> Async.Parallel |> Async.RunSynchronously
// int array — same order as input

Error handling uses regular try/with inside the block:

let safeFetch id = async {
    try
        let! r = fetch id
        return Ok r
    with ex ->
        return Error ex.Message
}

vs C# Task: F# Async values are cold — they don't run until started. C# Tasks are hot — they start immediately. F# now has task { ... } for direct C# Task interop, but pure F# code still uses async.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…