Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Layers
open Axial.Console
open Axial.FileSystem
open Axial.Hosting
open Axial.Hosting.Browser
open Axial.Hosting.Node
open Axial.HttpClient
open Axial.PlatformService
open Axial.Process
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptDeferred and Semaphore
Axial includes a small set of concurrency primitives only where they add Axial semantics over the .NET primitives underneath.
Use .NET Task, Channel<T>, SemaphoreSlim, and ConcurrentQueue<T> directly when raw platform behavior is enough. Use Axial primitives when coordination should preserve typed Exit and Cause, participate in workflow interruption, or release resources through the Flow model.
Deferred
Deferred<'error, 'value> is a one-shot handoff point between fibers. It can be completed once with a full Exit<'value, 'error>, so success, typed failure, defects, and interruption all remain visible to waiters.
Completion operations are idempotent. They return true to the caller that completed the deferred value and false to later callers.
let handoff : Flow<unit, string, int> =
flow {
let! deferred = Deferred.make<unit, string, int> ()
let! waiter =
Deferred.await deferred
|> Flow.fork
let! completed = Deferred.succeed 42 deferred
let! value = Flow.join waiter
if completed then
return value
else
return! Flow.fail "deferred was already completed"
}
handoff: Flow<unit,string,int>Axial.Flow`3Represents a cold workflow that reads an environment, returns a typed result, and is executed explicitly through one of its execution members such as ToTask, ToAsync, or RunSynchronously. The type of the environment dependency. The type of the failure value. The type of the success value.
unitThe type 'unit', which has only one value "()". This value is special and always uses the representation 'null'. Basic Types
stringAn abbreviation for the CLI type . Basic Types
intAn abbreviation for the CLI type . Basic Types
flow: FlowBuilderThe universal flow { } computation expression.
deferred: Deferred<string,int>Axial.DeferredModuleFlow-native helpers for one-shot typed coordination.
make: unit -> Flow<'env,'error,Deferred<'error,'value>>Creates an empty deferred value.
waiter: Fiber<string,int>await: Deferred<'error,'value> -> Flow<'env,'error,'value>Waits for the deferred outcome, preserving success, typed failure, defect, or interruption.
(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
Axial.Flowfork: Flow<'env,'error,'value> -> Flow<'env,'none,Fiber<'error,'value>>Starts a flow in a new fiber without waiting for it to complete. Forking turns a cold flow description into hot child work and returns a handle that can later be joined or interrupted. Prefer zipPar or race when the caller only needs a simple parallel composition. The flow to fork. A flow that produces a handle.
completed: boolsucceed: 'value -> Deferred<'error,'value> -> Flow<'env,'workflowError,bool>Attempts to complete the deferred value successfully.
value: intjoin: Fiber<'error,'value> -> Flow<'env,'error,'value>Waits for a fiber to complete and returns its successful value or typed failure. Joining preserves the child workflow's error channel. If the child failed with Cause.Fail, the joined flow fails with the same typed error; interruption and defects remain interruption and defects. The fiber to join. A flow that completes with the fiber's outcome.
fail: 'error -> Flow<'env,'error,'value>Alias for error that reads well in some call sites. The error value to wrap in a failing flow. A flow that always fails with the provided error. let result = Flow.fail "error" |> Flow.run () // result = Failure (Cause.Fail "error")
Deferred.awaitwaits for the outcome and resumes with the same success or failure.Deferred.completecompletes with a fullExit.Deferred.succeed,Deferred.fail,Deferred.die, andDeferred.interruptcomplete common outcomes directly.
Awaiting respects runtime cancellation. If the waiting workflow is interrupted before the deferred value is completed, the await returns Cause.Interrupt.
Semaphore
FlowSemaphore limits how many workflows can enter a section at the same time. The public API is intentionally scoped: use Semaphore.withPermit instead of raw acquire/release.
let limitedFetch semaphore request =
Semaphore.withPermit semaphore (
flow {
// Only one workflow per permit can run this section.
return! runRequest request
})Create semaphores with a positive permit count:
let program : Flow<unit, string, unit> =
flow {
let! semaphore = Semaphore.make 4
do! Semaphore.withPermit semaphore doWork
}Queues
Axial does not currently expose a queue primitive. A useful Axial queue needs more than a thin wrapper over Channel<T>: bounded strategy, shutdown, blocked offerer/taker interruption, fairness, and resource cleanup all need explicit semantics.
Until a v1 feature needs those semantics, use .NET channels directly at the edge of a workflow and convert operations into Flow where needed.

