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.JavaScriptDependencies
Start with ordinary function arguments. Reach for an environment when several workflows need the same dependencies and threading them through unrelated callers has become noise.
Then pass Flow a record. A workflow states what it needs in its environment channel; you build that record and hand it over when the workflow runs:
type AppEnv =
{ Users: IUserStore
Audit: IAuditLog }
let loadUser id : EnvFlow<AppEnv, User> =
flow {
let! users = Flow.envWith _.Users
return! users.Load id
}
let exit = loadUser userId |> Flow.run { Users = liveUsers; Audit = liveAudit }Two things build on it, and neither is needed to start. Contracts let a package ask for a service without
knowing your record type; that is how Console.writeLine and the rest of the
built-in services work, and how you would publish your own. Layers are for provisioning
that is itself effectful — see layers, a separate package.
In this section
- The environment — what
'envactually is, and the functions that read it. - Choosing an approach — arguments, records, contracts, and layers compared.
- Service contracts — how a package asks for a dependency it cannot name.
- Providing the environment — building the value at a host boundary.
- Tutorials — the same material worked end to end.
For the services Axial already implements — the clock, console, file system, processes, and HTTP — see built-in services.

