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.JavaScriptThe Environment
There is no container and no registration step. 'env is an ordinary type parameter, and the value you supply is an
ordinary value.
open Axial
let doubled : Flow<int, Never, int> =
Flow.envWith (fun environment -> environment * 2)
let result = doubled |> Flow.run 21 // Success 42
Axialdoubled: Flow<int,Never,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.
intAn abbreviation for the CLI type . Basic Types
Axial.NeverRepresents an error channel that cannot occur.
Axial.FlowenvWith: ('env -> 'value) -> Flow<'env,'error,'value>Projects one value from the current environment. This is the primary way to access app dependencies, configuration, or request metadata stored in env. The projection runs only when the flow is executed, so constructing the flow is still pure and side-effect free. Prefer small projections over passing a large environment deeper into reusable helpers. A function that extracts a value from the environment. A containing the projected value. let currentTime () = Flow.envWith (fun (environment: BaseRuntime) -> environment.Clock.UtcNow())
environment: int(*): ^T1 -> ^T2 -> ^T3Overloaded multiplication operator The first parameter. The second parameter. The result of the operation. 8 * 6 // Evaluates to 48
result: Exit<int,Never>(|>): '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
run: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
What the functions do
Flow.envWith runs a function against the environment and continues with the result:
Flow.envWith (fun environment -> environment.Users) // 'env -> 'a, giving Flow<'env, _, 'a>The rest of the environment surface is equally small:
| Function | What it does |
|---|---|
Flow.envWith projection |
Runs projection against the environment, continues with its result |
Flow.envWith id |
Continues with the environment value itself |
Flow.localEnv change |
Runs a flow against a different environment computed by change |
Flow.localEnv is how a workflow needing a small environment runs inside one that has more:
let usersOnly : Flow<IUserStore, AppError, User> = ...
let inTheApp : Flow<AppEnv, AppError, User> =
usersOnly |> Flow.localEnv (fun app -> app.Users)An int proves the point but is not the shape you want. In practice the environment is a record you define,
holding one field per dependency:
type AppEnv =
{ Users: IUserStore
Audit: IAuditLog }
let loadUser id : EnvFlow<AppEnv, User> =
flow {
let! users = Flow.envWith _.Users
return! users.Load id
}- At boot, with the live implementations.
- In tests, with fakes — the same record type, different values.
let live = { Users = SqlUserStore(connection); Audit = FileAuditLog(path) }
let underTest = { Users = InMemoryUserStore(); Audit = NullAuditLog() }
loadUser 42 |> Flow.run live
loadUser 42 |> Flow.run underTestWhere the rest of the section goes
That is the whole model. Everything after this page exists for cases the plain record does not cover:
- Choosing an approach — when arguments beat a record, and when a record stops being enough.
- Service contracts — how a package asks for a dependency without knowing your record type.
- Providing the environment — building the value at a host boundary.

