[{"categories":null,"content":"This page shows the source-documented Flow surface: the core type and module functions.\nCore type FsFlow.Flow: Represents a cold workflow that reads an environment, returns a typed result, and is executed explicitly through Flow.run. Module functions FsFlow.Flow.run: Executes a flow with the provided environment and the default cancellation token. FsFlow.Flow.ok: Creates a successful synchronous flow. FsFlow.Flow.error: Creates a failing synchronous flow. FsFlow.Flow.succeed: Alias for ok that reads well in some call sites. FsFlow.Flow.value: Alias for ok that reads well in some call sites. FsFlow.Flow.fail: Alias for error that reads well in some call sites. FsFlow.Flow.fromResult: Lifts a Result into a synchronous flow. FsFlow.Flow.fromOption: Lifts an option into a synchronous flow with the supplied error. FsFlow.Flow.fromValueOption: Lifts a value option into a synchronous flow with the supplied error. FsFlow.Flow.orElseFlow: Turns a pure validation result into a synchronous flow with environment-provided failure. FsFlow.Flow.env: Reads the current environment as the flow value. FsFlow.Flow.read: Projects a value from the current environment. FsFlow.Flow.map: Maps the successful value of a synchronous flow. FsFlow.Flow.bind: Sequences a synchronous continuation after a successful value. FsFlow.Flow.tap: Runs a synchronous side effect on success and preserves the original value. FsFlow.Flow.tapError: Runs a synchronous side effect on failure and preserves the original error. FsFlow.Flow.mapError: Maps the error value of a synchronous flow. FsFlow.Flow.catch: Catches exceptions raised during execution and maps them to a typed error. FsFlow.Flow.orElseWith: Falls back to another flow when the source flow fails. FsFlow.Flow.orElse: Falls back to another flow when the source flow fails. FsFlow.Flow.zip: Combines two flows into a tuple of their values. FsFlow.Flow.map2: Combines two flows with a mapping function. FsFlow.Flow.map3: Combines three flows with a mapping function. FsFlow.Flow.apply: Applies a flow-wrapped function to a flow-wrapped value. FsFlow.Flow.ignore: Maps the successful value of a synchronous flow to unit. FsFlow.Flow.localEnv: Transforms the environment before running the flow. FsFlow.Flow.provideLayer: Provides a derived environment from a layer flow to a downstream flow. FsFlow.Flow.delay: Defers flow construction until execution time. FsFlow.Flow.traverse: Transforms a sequence of values into a flow and stops at the first failure. FsFlow.Flow.sequence: Transforms a sequence of flows into a flow of a sequence and stops at the first failure. Concurrency FsFlow.Fiber: Represents a handle to a running workflow. FsFlow.Flow.fork: Starts a flow in a new fiber without waiting for it to complete. FsFlow.Flow.join: Waits for a fiber to complete and returns its final outcome. FsFlow.Flow.interrupt: Signals a fiber to stop and waits for it to finish its cleanup. Parallel orchestration FsFlow.Flow.zipPar: Combines two flows into a tuple of their values, running them concurrently. FsFlow.Flow.race: Runs two flows concurrently and returns the result of the first one to complete. ","description":"","linkTitle":"Flow","tags":null,"title":"Flow","uri":"/reference/flow/"},{"categories":null,"content":"FsToolkit.ErrorHandling If you are coming from FsToolkit.ErrorHandling, you will find that FsFlow is orthogonal rather than a direct replacement. While both libraries help with result-based programming, FsFlow focuses on a unified execution model that carries environments and runtime policies.\nThe Model Difference FsToolkit.ErrorHandling provides a broad toolbox of helpers for working with Result, AsyncResult, and TaskResult as separate, wrapped types.\nFsFlow provides a single, scalable progression:\n[Check](/reference/check/) -\u0026gt; [Result](/reference/result/) -\u0026gt; [Validation](/reference/validation/) -\u0026gt; [Flow](/reference/flow/) In FsFlow, the environment and runtime concerns are baked into the computation, allowing you to write orchestration logic that remains agnostic of whether the underlying work is sync or async until it hits the application boundary.\nHow Things Map If you use these FsToolkit patterns, here is how they correspond to FsFlow:\nFsToolkit.ErrorHandling FsFlow Result.requireTrue `Check.okIf condition Result.requireSome `Check.okIfSome opt asyncResult { } flow {} taskResult { } flow {} Validation helpers Validation and validate {} New Things You Get By using FsFlow for your orchestration layer, you gain several capabilities not present in standard result wrappers:\nUnified Environment: Every flow has access to an explicit 'env, removing the need to manually thread dependencies through every function. Runtime Policies: Retries, timeouts, and logging are first-class citizens in the Flow.Runtime module. Task Temperature: Built-in support for ColdTask, ensuring tasks only start when the flow is actually executed. Diagnostics Graph: A structured, path-aware error graph for complex validation that goes beyond a flat list of errors. Getting the Most Benefit You will get the most benefit from FsFlow by using it at your application boundaries (e.g., API handlers, background jobs) while keeping your pure domain logic in plain Result functions.\nKeep existing pure helpers: If you have a library of Result transformation helpers from FsToolkit, keep using them! FsFlow\u0026rsquo;s flow {} builders bind Result directly. Move orchestration: Use Flow when you need to combine those pure functions with I/O, configuration, or operational policies. Semantic Boundary FsFlow flows are short-circuiting by default. If your current FsToolkit usage leans on independent validation that should report multiple errors, use Validation and validate {} to maintain that explicit concern.\nlet validateUser cmd = validate { let! name = requireName cmd.Name and! email = requireEmail cmd.Email return { cmd with Name = name; Email = email } } This ensures that the \u0026ldquo;accumulating\u0026rdquo; vs \u0026ldquo;fail-fast\u0026rdquo; semantics remain clear in your code.\n","description":"Comparing FsFlow and FsToolkit.ErrorHandling models and how they work together.","linkTitle":"FsToolkit.ErrorHandling","tags":null,"title":"FsToolkit.ErrorHandling","uri":"/docs/ecosystem/integrations-fstoolkit/"},{"categories":null,"content":"Getting Started FsFlow is a toolkit for building robust, Result-based programs in F#. It allows you to scale from simple validation logic to complex, effectful application boundaries using a single, unified mental model.\n1. The Continuum of Logic FsFlow is designed around a continuum. You should always use the simplest tool that satisfies your current requirement:\nPure Checks -\u0026gt; Result \u0026amp; Validation -\u0026gt; Flow Pure Checks: Reusable predicates for basic validation. Result \u0026amp; Validation: Domain logic that handles success or failure (either fail-fast or error-accumulating). Flow: The application boundary where you need dependencies, async/task interop, logging, or cancellation. 2. Start with Checks and Results Most logic starts pure. Use Check for reusable predicates and Result for domain logic.\nopen FsFlow open FsFlow.Check type UserError = | NameTooShort let validateName (name: string) : Result\u0026lt;string, UserError\u0026gt; = name |\u0026gt; minLength 3 |\u0026gt; orError NameTooShort // This is just a standard F# Result. No magic yet. let result = validateName \u0026#34;Ad\u0026#34; // Error NameTooShort 3. Moving to Flow When your logic needs to interact with the outside world—by calling a database, reading an environment variable, or performing an async task—you move to Flow.\nA Flow\u0026lt;'env, 'error, 'value\u0026gt; is a description of a computation. It doesn\u0026rsquo;t do anything until you run it.\nlet greetUser (id: int) : Flow\u0026lt;unit, UserError, string\u0026gt; = flow { // You can bind a Result directly! let! name = validateName \u0026#34;Adam\u0026#34; // You can perform Async or Task work directly! let! (data: string) = async { return $\u0026#34;Hello {name}\u0026#34; } return data } 4. Execution: Turning Description into Action Because a Flow is just a description, you must explicitly run it. This is the boundary where your platform-independent logic meets the real world.\nWhen you call Flow.run, you provide the required environment (which can be () if none is needed) and a cancellation token is handled for you (defaulting to CancellationToken.None).\nExecution Handle vs. Outcome Because a Flow is just a description, you must explicitly run it. FsFlow handles the platform differences for you:\nFlow.run returns an Effect\u0026lt;'value, 'error\u0026gt;. The platform-specific carrier is defined by the target:\nOn .NET: Effect\u0026lt;'value, 'error\u0026gt; is a ValueTask\u0026lt;Exit\u0026lt;'value, 'error\u0026gt;\u0026gt;. On Fable: Effect\u0026lt;'value, 'error\u0026gt; is an Async\u0026lt;Exit\u0026lt;'value, 'error\u0026gt;\u0026gt;. The Exit Outcome The final result of any flow is an Exit\u0026lt;'value, 'error\u0026gt;. This type represents every possible outcome:\nmatch exitValue with | Exit.Success value -\u0026gt; printfn \u0026#34;Success: %A\u0026#34; value | Exit.Failure (Cause.Fail error) -\u0026gt; printfn \u0026#34;Expected domain error: %A\u0026#34; error | Exit.Failure (Cause.Die ex) -\u0026gt; printfn \u0026#34;Unexpected defect: %s\u0026#34; ex.Message | Exit.Failure Cause.Interrupt -\u0026gt; printfn \u0026#34;The workflow was cancelled.\u0026#34; 5. Running Your First Flow Here is how you actually execute a flow in a real application:\nlet myFlow = Flow.succeed \u0026#34;Hello World\u0026#34; // On .NET: let exit = Flow.run () myFlow // On Fable: let runOnFable () = async { let! exit = Flow.run () myFlow match exit with | Exit.Success s -\u0026gt; printfn \u0026#34;%s\u0026#34; s | _ -\u0026gt; () } 6. Reading from the Environment One of Flow\u0026rsquo;s greatest strengths is managing dependencies without manual parameter passing.\ntype AppConfig = { ApiUrl: string } let fetchFromApi : Flow\u0026lt;AppConfig, unit, string\u0026gt; = flow { // Read just the ApiUrl from the environment record let! url = Flow.read _.ApiUrl return $\u0026#34;Fetching from {url}...\u0026#34; } // Running with an environment let config = { ApiUrl = \u0026#34;https://api.example.com\u0026#34; } let effect = Flow.run config fetchFromApi Summary: The Flow Lifecycle Define: Use flow {} to describe your logic and its requirements. Compose: Combine smaller flows, Results, Tasks, and Asyncs into larger ones. Run: Call Flow.run env at your application\u0026rsquo;s entry point (e.g., a Controller or Main function). Handle: Match on the Exit value to handle success, failure, or defects. Next Steps Managing Dependencies: Learn how to structure your environments using the Record or CAPS patterns. Execution Semantics: Understand short-circuiting, \u0026ldquo;cold\u0026rdquo; vs \u0026ldquo;hot\u0026rdquo; tasks, and interruption. Task and Async Interop: A deep dive into binding different effect types. ","description":"The fastest path from Check and Result into Flow.","linkTitle":"Getting Started","tags":null,"title":"Getting Started","uri":"/docs/start/getting-started/"},{"categories":null,"content":"Pure Checks Check\u0026lt;'value\u0026gt; is the foundation of FsFlow validation. It is a reusable predicate layer that returns Result\u0026lt;'value, unit\u0026gt;.\nIf the predicate is true, it returns Ok value. If the predicate is false, it returns Error (). By returning unit on failure, Check stays agnostic about your application\u0026rsquo;s error types. You decide what the error means at the boundary where you use it.\nThe Two Shapes of Check Value-Preserving: Check\u0026lt;'value\u0026gt; - returns the input value on success. let check = Check.notBlank // string -\u0026gt; Result\u0026lt;string, unit\u0026gt; Gate: Check\u0026lt;unit\u0026gt; - returns unit on success (useful for yes/no questions). let check = Check.okIf (age \u0026gt; 18) // unit -\u0026gt; Result\u0026lt;unit, unit\u0026gt; Attaching Errors with Check.orError Use Check.orError to turn a unit failure into a meaningful application error.\ntype ValidationError = | NameRequired | InvalidAge let validateName name = name |\u0026gt; Check.notBlank |\u0026gt; Check.orError NameRequired let validateAge age = age |\u0026gt; Check.okIf (age \u0026gt; 0) |\u0026gt; Check.orError InvalidAge Common Helpers The Check module includes many built-in helpers:\nCheck.notBlank, Check.notNull, Check.notEmpty Check.okIf, Check.failIf Check.equal, Check.notEqual Check.okIfSome, Check.okIfValueSome Why use Checks? Reusability: Write a check once, use it in result {}, validate {}, or any Flow. Composition: You can combine checks using Check.and and Check.or. Decoupling: Pure logic doesn\u0026rsquo;t need to know about your logging or your database. ","description":"Reusable predicate layer with the Check module.","linkTitle":"Pure Checks","tags":null,"title":"Pure Checks","uri":"/docs/validation-results/checks/"},{"categories":null,"content":"Ref (Atomic References) Ref\u0026lt;'T\u0026gt; is a handle to a mutable reference that can be updated atomically. It is the simplest way to manage shared state between multiple concurrent parts of your application.\nNote: Ref is currently available on .NET only.\nWhy Use Ref? In a functional program, state is usually passed as parameters or through the environment. However, some scenarios—like a shared counter, a cache, or a status flag—require multiple concurrent workflows to observe and update the same value.\nRef provides a thread-safe way to do this without manual lock or Monitor calls.\nCreating a Ref Use Ref.make to create a new reference with an initial value. Like all things in FsFlow, creating a Ref is an effectful operation that returns a Flow.\nlet counterWorkflow = flow { let! counter = Ref.make 0 return counter } Reading and Writing Use Ref.get to read the current value and Ref.set to overwrite it.\nlet workWithRef (counter: Ref\u0026lt;int\u0026gt;) = flow { let! value = Ref.get counter printfn \u0026#34;Current value: %d\u0026#34; value do! Ref.set (value + 1) counter } Atomic Updates For concurrent safety, you should use Ref.update or Ref.modify. These operations ensure that the update is atomic, preventing race conditions when multiple fibers are updating the same reference simultaneously.\nRef.update Updates the value using a transformation function.\nlet increment (counter: Ref\u0026lt;int\u0026gt;) = Ref.update (fun x -\u0026gt; x + 1) counter Ref.modify Updates the value and returns a derived result (a common pattern for \u0026ldquo;get and increment\u0026rdquo;).\nlet incrementAndGet (counter: Ref\u0026lt;int\u0026gt;) = Ref.modify (fun x -\u0026gt; let next = x + 1 next, next // (new state, return value) ) counter Example: Shared Progress Tracker let trackProgress (total: int) = flow { let! progress = Ref.make 0 let doStep = flow { let! current = Ref.modify (fun p -\u0026gt; p + 1, p + 1) progress printfn \u0026#34;Progress: %d/%d\u0026#34; current total } // Run several steps for _ in 1 .. total do do! doStep return \u0026#34;Complete\u0026#34; } API Reference Function Signature Description make 'T -\u0026gt; Flow\u0026lt;'env, 'none, Ref\u0026lt;'T\u0026gt;\u0026gt; Creates a new reference with an initial value. get Ref\u0026lt;'T\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'none, 'T\u0026gt; Reads the current value of the reference. set 'T -\u0026gt; Ref\u0026lt;'T\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'none, unit\u0026gt; Sets the value of the reference to a new value. update ('T -\u0026gt; 'T) -\u0026gt; Ref\u0026lt;'T\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'none, unit\u0026gt; Atomically updates the value using the supplied function. modify ('T -\u0026gt; 'T * 'v) -\u0026gt; Ref\u0026lt;'T\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'none, 'v\u0026gt; Atomically updates the value and returns a derived result. ","description":"Shared mutable state with atomic updates in FsFlow.","linkTitle":"Ref (Atomic References)","tags":null,"title":"Ref (Atomic References)","uri":"/docs/state-concurrency/ref/"},{"categories":null,"content":"","description":"","linkTitle":"Start","tags":null,"title":"Start","uri":"/docs/start/"},{"categories":null,"content":"","description":"","linkTitle":"Core Model","tags":null,"title":"Core Model","uri":"/docs/core-model/"},{"categories":null,"content":"Welcome to the FsFlow guides. Choose a section from the sidebar or start with Getting Started.\nStart Getting oriented Install the package, see tiny examples, and learn the validation-first path into real app boundaries.\nValidation \u0026 Results Pure Checks and Results Overview of the FsFlow validation stack, from pure checks to structured diagnostics.\nCore Model How FsFlow fits together Read the semantics, task or async interop rules, and architectural styles.\nManaging Dependencies Environment handling Learn how to manage dependencies using the Record Pattern or CAPS pattern.\nState and Concurrency Concurrent workflows Manage shared state, coordination, retries, and streaming.\nPatterns Usage patterns Use runnable examples, benchmarks, and type troubleshooting notes while applying FsFlow.\nEcosystem Integrations Map FsFlow alongside Validus, FsToolkit.ErrorHandling, FSharpPlus, IcedTasks, and Effect-TS.\n","description":"","linkTitle":"Docs","tags":null,"title":"Docs","uri":"/docs/"},{"categories":null,"content":"Environment Slicing (The Record Pattern) The Record Pattern is the most common way to manage dependencies in FsFlow. It uses standard F# records to define the \u0026ldquo;world\u0026rdquo; a workflow lives in.\nProjecting from the Environment When a workflow needs a dependency, it \u0026ldquo;reads\u0026rdquo; it from the environment record.\ntype AppEnv = { Gateway: IPingGateway Logger: ILogger } let ping = flow { // \u0026#39;env\u0026#39; is the full AppEnv record let! gateway = Flow.read (fun env -\u0026gt; env.Gateway) return! gateway.Ping() } The Shorthand: _.Field F# provides a nice shorthand for these simple projections. Instead of (fun env -\u0026gt; env.Gateway), you can write _.Gateway. This makes the code much cleaner and easier to read.\nlet ping = flow { let! gateway = Flow.read _.Gateway let! logger = Flow.read _.Logger logger.Info \u0026#34;Starting ping\u0026#34; return! gateway.Ping() } Slicing with localEnv \u0026ldquo;Slicing\u0026rdquo; is the process of taking a large environment and projecting it down to a smaller one required by a sub-flow. This keeps your workflows \u0026ldquo;honest\u0026rdquo;—they only see the dependencies they actually use.\ntype SmallEnv = { Logger: ILogger } let smallWorkflow : Flow\u0026lt;SmallEnv, unit, unit\u0026gt; = ... let bigWorkflow : Flow\u0026lt;AppEnv, unit, unit\u0026gt; = smallWorkflow |\u0026gt; Flow.localEnv (fun env -\u0026gt; { Logger = env.Logger }) Splitting Runtime Services from App Dependencies In complex apps, you often want to separate Operational Services (logging, metrics, cancellation) from Application Services (gateways, repositories). FsFlow provides RuntimeContext\u0026lt;'runtime, 'env\u0026gt; for this.\ntype RuntimeServices = { Log: string -\u0026gt; unit } type AppEnv = { Gateway: IPingGateway } let workflow : Flow\u0026lt;RuntimeContext\u0026lt;RuntimeServices, AppEnv\u0026gt;, unit, unit\u0026gt; = flow { // Read from the \u0026#39;runtime\u0026#39; half let! log = Flow.readRuntime _.Log // Read from the \u0026#39;env\u0026#39; half let! gateway = Flow.readEnvironment _.Gateway log \u0026#34;starting\u0026#34; return! gateway.Ping() } The Capability Module The Capability module provides helpers for the main Flow surface and the RuntimeContext split using a single API.\nCapability.service: Polymorphic version of read. Capability.runtime: Polymorphic version of readRuntime. Capability.environment: Polymorphic version of readEnvironment. let log message = flow { let! logger = Capability.service _.Logger logger.Log message } Layering and Composition Layers are flows that produce a derived environment. Use Flow.provideLayer to \u0026ldquo;connect\u0026rdquo; a layer to a downstream workflow.\nlet appLayer : Flow\u0026lt;RuntimeServices, AppError, AppDependencies\u0026gt; = ... let workflow : Flow\u0026lt;AppDependencies, AppError, Response\u0026gt; = ... let runnable = workflow |\u0026gt; Flow.provideLayer appLayer The downstream workflow stays typed against the smaller environment, while the final runnable workflow accepts the outer environment needed to build it.\nNext Steps If you need to decouple your workflows from specific record types entirely (e.g., for a shared library), read about the CAPS Pattern.\n","description":"Deep dive into the Record Pattern for dependency management.","linkTitle":"Environment Slicing","tags":null,"title":"Environment Slicing","uri":"/docs/managing-dependencies/env-slicing/"},{"categories":null,"content":"Execution Semantics This page shows the exact execution rules for Flow, including how a cold program becomes an Effect and resolves to an Exit.\nFsFlow uses a unified Flow\u0026lt;'env, 'error, 'value\u0026gt; model that handles synchronous code, F# Async, and .NET Task interop natively.\nExecution Shape Conceptually, execution is:\nFlow -\u0026gt; Effect -\u0026gt; Exit\nMore precisely:\nFlow is the cold program you define. Effect is the deferred runnable carrier. Exit is the terminal outcome after execution. Success and Typed Failure Every Flow execution results in an Exit\u0026lt;'value, 'error\u0026gt;:\nExit.Success value: The happy path. Exit.Failure (Cause.Fail error): An expected domain-specific failure. Exit.Failure Cause.Interrupt: The workflow was signaled to stop (e.g., cancellation). Exit.Failure (Cause.Die exception): An unexpected defect or crash. All standard combinators (map, bind, zip, orElse) are short-circuiting. The first Exit.Failure stops the workflow unless explicitly caught.\nShort-Circuiting vs. Accumulated Validation flow {} and result {}: Ordered workflows. They stop on the first failure. validate {}: Accumulating validation. Joins errors from independent steps (using and!) into a structured Diagnostics graph. Use the short-circuiting model when later steps depend on earlier values. Use the validation model when independent checks should all run and report back together.\nExecution Is Explicit You run a Flow by calling Flow.run.\nFlow.run returns an Effect\u0026lt;'value, 'error\u0026gt;. The platform-specific carrier is defined by the target:\nOn .NET: Effect\u0026lt;'value, 'error\u0026gt; is a ValueTask\u0026lt;Exit\u0026lt;'value, 'error\u0026gt;\u0026gt;. On Fable: Effect\u0026lt;'value, 'error\u0026gt; is an Async\u0026lt;Exit\u0026lt;'value, 'error\u0026gt;\u0026gt;. This design allows FsFlow to remain portable while respecting the execution models of different platforms. Effect is the cross-platform execution handle.\nA flow is cold: building a flow does not run it. Each call to run executes the logic from scratch.\nWhy Exit Has Three Failure Causes Exit.Failure carries a Cause\u0026lt;'error\u0026gt; instead of a plain error because not all failures mean the same thing.\nCause.Fail error: An expected domain failure. This is the normal typed error path. Cause.Interrupt: A cancellation or interruption signal. The runtime uses this when a workflow stops because it was asked to stop. Cause.Die exception: An unexpected defect or crash. This is for bugs, panic-like failures, and exceptions that were not intentionally translated into a typed error. This split matters because one generic failure type cannot answer three different questions:\nWas this a business-rule failure that should participate in normal control flow? Was this a cancellation signal that should stop work immediately and usually not be retried? Was this a defect that should usually surface as a crash or be logged as an unexpected exception? Why Not Just Use CancellationToken? CancellationToken only models interruption. It does not model:\na typed domain error like Cause.Fail a defect like Cause.Die the fact that a flow can fail for reasons other than cancellation FsFlow still uses CancellationToken internally and for interoperability, but it converts cancellation into Cause.Interrupt at the edges where the runtime can observe it. That keeps cancellation as a first-class execution outcome instead of burying it inside the ambient .NET token API.\nHow Each Cause Gets Produced Cause.Fail is produced by explicit domain failures such as Flow.error, Flow.fail, Flow.fromResult, and validation branches that intentionally turn a rejected condition into a typed error. Cause.Interrupt is produced when the runtime observes cancellation or interruption, such as Flow.interrupt or a cancellation-aware helper like Flow.Runtime.sleep. Cause.Die is produced by defects that escape normal typed handling, such as unexpected exceptions. The runtime generally does not invent this value for you; it preserves the defect unless you intentionally catch and translate it. Where The Runtime Helps The runtime already does some of the translation work:\ncancellation-aware helpers convert OperationCanceledException into Cause.Interrupt exception-catching helpers like Flow.catch translate exceptions into Cause.Fail when you want them treated as domain errors Exit.toResult re-raises Cause.Die and Cause.Interrupt when you collapse back into a plain Result, because those are not normal success-path errors Interruption and Cancellation FsFlow supports algebraic interruption. When a fiber is interrupted (e.g., via Flow.interrupt or a CancellationToken trigger), the flow stops executing and returns Exit.Failure Cause.Interrupt.\nEnvironments Flow reads dependencies explicitly:\nFlow.env: Reads the whole environment. Flow.read: Projects one dependency. Flow.localEnv: Runs a smaller computation inside a larger environment. Task Temperature Flow distinguishes between:\nHot Inputs: Already-started Task\u0026lt;'value\u0026gt; or Async\u0026lt;'value\u0026gt;. Re-running the flow re-awaits the same underlying work. Cold Inputs: Logic defined inside flow {} or helpers like Flow.Runtime.sleep. Re-running the flow repeats the work. Use Cold inputs when you want the effect to observe the runtime CancellationToken or repeat its side effects on retry.\nRuntime Helpers Operational helpers for logging, timeout, retry, and resource handling are grouped into the Flow.Runtime and Schedule modules.\nNext Read Getting Started for a tutorial-style overview, or browse the API Reference for detailed signatures.\n","description":"Exact execution rules for Flow.","linkTitle":"Execution Semantics","tags":null,"title":"Execution Semantics","uri":"/docs/core-model/semantics/"},{"categories":null,"content":"Result CE Use the result {} computation expression when you have a sequence of steps where each step depends on the previous one, and you want to stop at the first failure.\nThis is \u0026ldquo;fail-fast\u0026rdquo; semantics.\nBasic Usage The result {} builder binds standard F# Result\u0026lt;'value, 'error\u0026gt; types.\ntype UserError = | MissingName | MissingEmail let validateUser name email = result { // If name is blank, it returns Error MissingName and stops. let! validName = name |\u0026gt; Check.notBlank |\u0026gt; Check.orError MissingName // This line only runs if the name was valid. let! validEmail = email |\u0026gt; Check.notBlank |\u0026gt; Check.orError MissingEmail return { Name = validName; Email = validEmail } } Guarded Bindings Guard is a powerful companion to result {}. It allows you to bind boolean or check-shaped sources directly while attaching an error value at the binding site.\nlet login username password = result { // If password is blank, fails with MissingPassword do! Check.notBlank password |\u0026gt; Guard.Of MissingPassword // If user not found, maps the underlying error to Unauthorized let! user = tryGetUser username |\u0026gt; Guard.MapError (fun _ -\u0026gt; Unauthorized) return user } When to use result {} Sequential Dependencies: When Step B requires the output of Step A. Fail-Fast: When continuing after an error makes no sense (e.g., you can\u0026rsquo;t save a user if the email is invalid). Simple Logic: When you only need to return a single error value to the caller. If you need to collect multiple independent errors at once, use validate {} instead.\n","description":"Fail-fast composition with the result { } builder.","linkTitle":"Result CE","tags":null,"title":"Result CE","uri":"/docs/validation-results/result-ce/"},{"categories":null,"content":"Schedule (Retry \u0026amp; Repeat) The Schedule module provides a powerful DSL for describing policies that govern how and when a workflow should be executed again. You can use schedules to implement sophisticated retry strategies (like exponential backoff with jitter) or recurring tasks.\nNote: Schedule is currently available on .NET only.\nBasic Schedules A schedule decides two things:\nWhether to continue (recur). How long to wait before the next attempt. Fixed Number of Recursions // Recur 5 times (6 attempts total) let fiveTimes = Schedule.recurs 5 Fixed Spacing // Recur indefinitely with 1 second between attempts let everySecond = Schedule.spaced (TimeSpan.FromSeconds 1.0) Exponential Backoff // Delays: 100ms, 200ms, 400ms, 800ms... let backoff = Schedule.exponential (TimeSpan.FromMilliseconds 100.0) Adding Jitter Jitter adds randomness to delays to prevent \u0026ldquo;thundering herd\u0026rdquo; problems in distributed systems. Schedule.jittered adds a random factor between 0.5x and 1.5x to the current delay.\nlet policy = Schedule.exponential (TimeSpan.FromMilliseconds 100.0) |\u0026gt; Schedule.jittered Retrying Failures Use Flow.Retry to apply a schedule to a flow that might fail with an expected domain error (Cause.Fail).\nImportant: If the flow fails with a defect (Cause.Die) or is interrupted (Cause.Interrupt), it will not be retried. This ensures that logic errors and cancellation signals are respected immediately.\nlet unstableCall = flow { printfn \u0026#34;Attempting call...\u0026#34; return! Flow.fail \u0026#34;temporary-error\u0026#34; } // This will attempt the call up to 4 times (initial + 3 retries) let resilientCall = Flow.Retry(unstableCall, Schedule.recurs 3) Repeating Successes Use Flow.Repeat to execute a successful flow again. This is useful for polling, heartbeats, or recurring background tasks.\nlet pollStatus = flow { printfn \u0026#34;Polling status...\u0026#34; return \u0026#34;Still working\u0026#34; } // This will poll every 5 seconds until it fails or is cancelled let recurringPoll = Flow.Repeat(pollStatus, Schedule.spaced (TimeSpan.FromSeconds 5.0)) API Reference: Module Schedule Function Signature Description recurs int -\u0026gt; Schedule\u0026lt;'env, 'i, int\u0026gt; Recurs exactly n times. The output value is the attempt index. spaced TimeSpan -\u0026gt; Schedule\u0026lt;'env, 'i, int\u0026gt; Recurs indefinitely with a fixed delay. exponential TimeSpan -\u0026gt; Schedule\u0026lt;'env, 'i, TimeSpan\u0026gt; Recurs indefinitely with doubling delays. jittered Schedule\u0026lt;'env, 'i, 'o\u0026gt; -\u0026gt; Schedule\u0026lt;'env, 'i, 'o\u0026gt; Wraps a schedule to add random jitter (0.5x to 1.5x). API Reference: Flow Extensions Function Signature Description Flow.Retry Flow\u0026lt;'e, 'err, 'v\u0026gt; * Schedule\u0026lt;'e, 'err, 'o\u0026gt; -\u0026gt; Flow\u0026lt;'e, 'err, 'v\u0026gt; Retries the flow on Cause.Fail. Flow.Repeat Flow\u0026lt;'e, 'err, 'v\u0026gt; * Schedule\u0026lt;'e, 'v, 'o\u0026gt; -\u0026gt; Flow\u0026lt;'e, 'err, 'v\u0026gt; Repeats the flow on success. ","description":"Declarative policies for retrying failures and repeating successes in FsFlow.","linkTitle":"Schedule (Retry \u0026 Repeat)","tags":null,"title":"Schedule (Retry \u0026 Repeat)","uri":"/docs/state-concurrency/schedule/"},{"categories":null,"content":"Troubleshooting Types This page shows the compiler errors that usually mean you crossed a wrapper boundary in the wrong place.\nMost FsFlow type errors are not exotic. The compiler usually sees one wrapper shape and you intended another.\nError: A Unique Overload For Method Bind Could Not Be Determined This usually happens when the compiler cannot tell which wrapper shape a let! value should use.\nExample:\nlet nested : Async\u0026lt;Async\u0026lt;Result\u0026lt;int, string\u0026gt;\u0026gt;\u0026gt; = async { return async { return Ok 42 } } let workflow : Flow\u0026lt;unit, string, int\u0026gt; = flow { let! next = nested let! value = next return value } The second let! is ambiguous.\nFix it with a type annotation:\nlet workflow : Flow\u0026lt;unit, string, int\u0026gt; = flow { let! next = nested let! (value: int) = next return value } Error: The Flow Requires A Different Environment Type This usually means you wrote a smaller workflow against one env type and are trying to run it inside a larger env.\nExample:\ntype SmallEnv = { Prefix: string } type BigEnv = { App: SmallEnv; RequestId: string } let greet : Flow\u0026lt;SmallEnv, string, string\u0026gt; = flow { let! prefix = Flow.read _.Prefix return $\u0026#34;{prefix} world\u0026#34; } If you want to run it in BigEnv, derive the smaller local env from the outer one:\nlet greetInBigEnv : Flow\u0026lt;BigEnv, string, string\u0026gt; = greet |\u0026gt; Flow.localEnv _.App Error: Option Or ValueOption Does Not Match Your Error Type Implicit option binding only works when the workflow error type is unit.\nThis fails:\nlet workflow : Flow\u0026lt;unit, string, int\u0026gt; = flow { let! value = Some 42 return value } Use an explicit adapter when you want a custom error:\nlet workflow : Flow\u0026lt;unit, string, int\u0026gt; = Some 42 |\u0026gt; Flow.fromOption \u0026#34;missing value\u0026#34; Error: ColdTask Does Not Match Task Flow.fromTask and direct flow { let! ... } support ColdTask\u0026lt;'value\u0026gt; for delayed task work.\nColdTask\u0026lt;'value\u0026gt; means:\nCancellationToken -\u0026gt; Task\u0026lt;\u0026#39;value\u0026gt; Wrap the factory explicitly:\nlet load : ColdTask\u0026lt;int\u0026gt; = ColdTask(fun _ -\u0026gt; Task.FromResult 42) If you already have a started Task\u0026lt;'value\u0026gt;, bind it directly in flow {} instead.\nWhen Type Errors Usually Mean A Boundary Problem If the compiler error mentions one of these shapes, check the boundary first:\nResult\u0026lt;...\u0026gt; Async\u0026lt;...\u0026gt; Async\u0026lt;Result\u0026lt;...\u0026gt;\u0026gt; Task\u0026lt;...\u0026gt; Task\u0026lt;Result\u0026lt;...\u0026gt;\u0026gt; Flow\u0026lt;...\u0026gt; Most fixes are one of:\nadd a type annotation to disambiguate let! overloads derive a smaller local environment with localEnv use Guard.Of or Guard.MapError to bridge existing error-bearing sources move back to plain Result until the real workflow boundary appears Next Read docs/GETTING_STARTED.md for the workflow overview, docs/TASK_ASYNC_INTEROP.md for the binding surface, and examples/FsFlow.MaintenanceExamples/Program.fs for runnable versions of these shapes.\n","description":"","linkTitle":"Troubleshooting Types","tags":null,"title":"Troubleshooting Types","uri":"/docs/patterns/troubleshooting-types/"},{"categories":null,"content":"Validation \u0026amp; Results FsFlow provides a unified stack for handling failure, ranging from pure predicate checks to complex, path-aware diagnostics graphs.\nThe core philosophy is to check once, lift later. You write your pure logic using simple tools and then lift them into richer execution contexts (like Flow or Flow) only when needed.\nThe Progression Pure Checks: Build reusable predicates with the Check module. Result \u0026amp; Validation: Domain logic that either fails fast (result {}) or accumulates multiple errors (validate {}). Guard: The bridge that allows pure checks and simple sources to fail a flow with a specific domain error. Flow: The application boundary where you need dependencies, async work, or interop. Why use this stack? Consistency: Use the same patterns for simple form validation and complex background job logic. Testability: Pure checks are trivial to test in isolation. Ergonomics: Computation expressions like result {} and validate {} make complex logic readable and idiomatic. Structured Reporting: Diagnostics graphs preserve the shape of your data, making it easy to report errors back to users or external systems. Getting Started If you are new to FsFlow, start with Pure Checks to see how the smallest building blocks work.\nSee it in Action For a complete, runnable example that demonstrates how these pieces fit together—from nested validation to JSON API error formatting—see the Diagnostics Example.\n","description":"Overview of the FsFlow validation stack, from pure checks to structured diagnostics.","linkTitle":"Validation \u0026 Results","tags":null,"title":"Validation \u0026 Results","uri":"/docs/validation-results/"},{"categories":null,"content":"Validus Integration This page shows how FsFlow can fit beside Validus validation pipelines.\nValidus is a strong choice when the problem is still validation, especially when you want a richer DSL, composition, accumulation, or value-object style checks.\nFsFlow can usually begin after that work is done.\nValidus and FsFlow.Check fit especially well together: Validus can handle richer validation rules, while FsFlow.Check stays available for smaller pure guards that feed directly into Result, Validation, or Flow.\nKeep Validation Before Workflow Orchestration The best division of labor is:\nValidus validates the incoming model or command FsFlow orchestrates the application boundary, environment, runtime, typed failure, and structured validation That keeps the validation step reusable and keeps the runtime boundary honest.\nHow They Fit Together Common patterns:\nvalidate with Validus convert the final success/failure into a plain Result bind that Result directly inside a flow when the workflow starts use Check when you want a smaller pure-guard layer without the heavier validation model Why The Pair Works Validus owns the validation story when composition, accumulation, or richer checks matter FsFlow.Check gives you a small, readable bridge when the check is a plain guard clause, option test, null check, or string predicate the flow family can then own the runtime boundary without swallowing validation concerns Example let validateCreateUser dto = if System.String.IsNullOrWhiteSpace dto.Name then Error \u0026#34;name required\u0026#34; else Ok dto let createUser : Flow\u0026lt;AppEnv, string, User\u0026gt; = flow { let! dto = validateCreateUser incoming let! tenant = Flow.read _.TenantId return { Name = dto.Name; TenantId = tenant } } If the validation story is already richer than FsFlow.Check or FsFlow.Validation, keep it richer. FsFlow can receive the outcome, not fight the validation library.\nWhen To Prefer FsFlow.Check Use FsFlow.Check when the checks are simple and can stay purely Result\u0026lt;'value, unit\u0026gt;-based:\nguard clauses option checks null checks string emptiness checks simple collection checks Use Validus when you want a more expressive validation DSL or validation accumulation and that library already fits your codebase.\n","description":"How FsFlow fits beside Validus validation pipelines.","linkTitle":"Validus Integration","tags":null,"title":"Validus Integration","uri":"/docs/ecosystem/integrations-validus/"},{"categories":null,"content":"The Guard The Guard is a bridge. It allows pure predicate checks and simple error-bearing sources (like Option or Result) to fail a computation with a specific domain error.\nWhile builders like flow {} and result {} can bind many types directly, Guard is the primary tool for assigning a domain-specific error to a source or \u0026ldquo;unwrapping\u0026rdquo; an effectful source before validation.\nWhy do I need Guard? Consider a simple user lookup. When it is a pure function, it works seamlessly with Check:\nopen FsFlow open FsFlow.Check type User = { Name: string } type AppError = UserNotFound | InvalidPassword // A pure \u0026#34;database\u0026#34; lookup let tryGetUser name : User option = let users = [ { Name = \u0026#34;ada\u0026#34; }; { Name = \u0026#34;bob\u0026#34; } ] users |\u0026gt; List.tryFind (fun u -\u0026gt; u.Name = name) let loginPure name = [`result {}`](/reference/result/builders-result/) { // This works: okIfSome expects an Option, which tryGetUser returns let! user = tryGetUser name |\u0026gt; okIfSome |\u0026gt; orError UserNotFound return user } However, in a real application, lookup usually requires a database connection from the environment or performs async work. Now it becomes a Flow:\n// In reality, this needs the environment and is effectful let tryGetUserFlow name : Flow\u0026lt;DbEnv, AppError, User option\u0026gt; = flow { let! db = Flow.read _.Db return! db.Users.TryFind name } If you try to use the same Check pattern inside a flow {} block, it will fail to compile:\nlet login name = flow { // COMPILE ERROR: tryGetUserFlow returns a Flow, but okIfSome expects an Option. // The builder hasn\u0026#39;t \u0026#34;unwrapped\u0026#34; the flow yet! let! user = tryGetUserFlow name |\u0026gt; Check.okIfSome |\u0026gt; Check.orError UserNotFound return user } Check functions expect pure types (like Option or string). They don\u0026rsquo;t know how to look \u0026ldquo;inside\u0026rdquo; a Flow.\nGuard is the bridge. It allows you to \u0026ldquo;mark\u0026rdquo; an effectful source so that the flow builder binds it first before applying the check:\nlet login name password = flow { // 1. Guard binds the flow, sees the Option, and applies the error logic let! user = tryGetUserFlow name |\u0026gt; Guard.Of UserNotFound // 2. You can also guard pure checks that haven\u0026#39;t been lifted yet do! notBlank password |\u0026gt; Guard.Of InvalidPassword return user } Common Guard Patterns Guarding Options Convert a Some value into success and None into a specific error:\nlet! user = maybeUser |\u0026gt; Guard.Of UserNotFound Guarding Checks Apply a pure predicate and fail the flow if it returns Error ():\ndo! notBlank password |\u0026gt; Guard.Of InvalidPassword Remapping Errors If a source already has an error, but it doesn\u0026rsquo;t match your flow\u0026rsquo;s error type, use Guard.MapError:\nlet! user = fetchUser id |\u0026gt; Guard.MapError (fun ex -\u0026gt; DatabaseError ex.Message) Summary Use Guard whenever you need to:\nAssign a domain error to a pure Check or Option inside a computation. \u0026ldquo;Unwrap\u0026rdquo; an effectful source that returns a simple type before validating it. Keep your business logic readable by avoiding manual matching or re-lifting inside your flows. ","description":"Bridging pure checks and effectful sources into Flow.","linkTitle":"The Guard","tags":null,"title":"The Guard","uri":"/docs/validation-results/guard/"},{"categories":null,"content":"Benchmarks This page shows the performance tradeoffs of using FsFlow compared to manual result/async/task composition.\nThe benchmarks are measured with BenchmarkDotNet and represent the abstraction cost for typical application code.\nSummary abstraction cost is negligible for effectful code cold execution for task-oriented computations adds small allocation overhead compared to hot ValueTask performance is competitive with manual Async\u0026lt;Result\u0026lt;'T, 'E\u0026gt;\u0026gt; composition Setup All measurements were taken on:\n.NET 8.0 Ubuntu 22.04 AMD Ryzen 9 5950X Abstraction Cost Measures a 20-step bind sequence where each step is pure. This is the \u0026ldquo;worst case\u0026rdquo; for FsFlow because the abstraction cost is not hidden by actual I/O or async work.\nSynchronous (Flow) Measures 20 steps of flow { let! x = Ok 1; return x + 1 } against manual result { let! x = Ok 1; return x + 1 }.\nMethod Mean Allocated Manual Result 12.4 ns - Flow 45.2 ns 160 B Task-Oriented (Flow) Measures the same 20-step short-circuiting shape for task-oriented computations.\nMethod Mean Allocated Manual Task\u0026lt;Result\u0026gt; 142.1 ns 640 B Flow 185.4 ns 1.2 KB Implicit Token Propagation Compares Flow implicit token propagation with explicit token threading in a manual Task\u0026lt;Result\u0026lt;_,_\u0026gt;\u0026gt; computation.\nMethod Mean Allocated Manual Threading 158.2 ns 720 B Flow 185.4 ns 1.2 KB The overhead is the cost of carrying the Env and CancellationToken through the computation expression.\nReal-World Scaling The abstraction cost is fixed per bind. In a real application where steps involve database access (1-10ms) or external API calls (50-200ms), the 40-200ns overhead is effectively zero.\nAsync Bound With I/O Simulation Measures a 5-step computation where each step yields to the thread pool.\nComputation FailAt Mean Allocated Manual Async - 1.2 us 480 B Flow - 1.4 us 720 B Manual Async Step 3 0.8 us 320 B Flow Step 3 0.9 us 480 B The important metric for teams is that the migration story is still defensible because the gap narrows when more of the computation actually runs.\nTask Bound With I/O Simulation Measures a 5-step computation where each step is an awaited Task.Yield().\nComputation FailAt Mean Allocated Manual Task - 2.1 us 1.2 KB Flow - 2.4 us 1.8 KB The relative gap shrinks as more of the computation executes.\nCold Execution Cost FsFlow computations are cold. Rerunning a computation re-executes all steps.\nRerunning 20 Steps Computation Mean Allocated Manual (Cached) 5.2 ns - FsFlow (Rerun) 45.2 ns 160 B If you need to cache a result, run the computation once and store the Result. The \u0026ldquo;cold\u0026rdquo; property is for effectful orchestration, not for caching data.\nValueTask Tradeoffs Flow uses ValueTask internally where possible, but the cold nature of the library means it cannot always avoid allocations when binding hot tasks.\nBinding Hot Task vs ColdTask Computation Mean Allocated Hot Task Bind 185.4 ns 1.2 KB ColdTask Bind 162.1 ns 840 B ColdTask is slightly faster and leaner because it avoids the ValueTask wrapper check when the work is already delayed.\nConclusion use FsFlow for architectural clarity and safety do not worry about the performance cost in the application layer it still does not override the correctness and reuse hazards of storing composed computations as ValueTask Full Results Computation Mean Allocated Flow.run 45.2 ns 160 B Flow.run 152.1 ns 960 B Flow.run 185.4 ns 1.2 KB Measurements taken with FsFlow.Benchmarks in the repository.\n","description":"","linkTitle":"Benchmarks","tags":null,"title":"Benchmarks","uri":"/docs/patterns/benchmarks/"},{"categories":null,"content":"Capabilities (CAPS) The CAPS pattern lets you decouple your workflows from specific record types. Instead of saying \u0026ldquo;I need the AppEnv record,\u0026rdquo; a workflow says \u0026ldquo;I need any environment that provides an IClock.\u0026rdquo;\nThis is achieved using the Needs\u0026lt;'dep\u0026gt; interface and the Env\u0026lt;'dep\u0026gt; request token.\nRequesting a Dependency with Env\u0026lt;'dep\u0026gt; In a CAPS workflow, you use the Env\u0026lt;'dep\u0026gt; token to request a dependency by its type. FsFlow handles finding that dependency in the environment for you.\nlet getTime = flow { // Request the IClock dependency directly let! clock = Env\u0026lt;IClock\u0026gt; return clock.UtcNow() } Projecting with Env\u0026lt;'dep\u0026gt; Just like Flow.read in the Record Pattern, you can project a value or call a method directly from the dependency using a lambda or the _.Field shorthand.\nlet readTime = flow { // Project UtcNow from the IClock dependency let! now = Env\u0026lt;IClock\u0026gt; (fun clock -\u0026gt; clock.UtcNow()) // Or use the shorthand let! now2 = Env\u0026lt;IClock\u0026gt; _.UtcNow return now } Satisfying the Contract with Needs\u0026lt;'dep\u0026gt; To run a CAPS workflow, your environment must implement the Needs\u0026lt;'dep\u0026gt; interface. This acts as the \u0026ldquo;glue\u0026rdquo; between your concrete implementation and the workflow\u0026rsquo;s requirements.\ntype MyRuntime = { ClockService: IClock } interface Needs\u0026lt;IClock\u0026gt; with member x.Dep = x.ClockService Named Cap Sets For complex boundaries, you can group multiple dependencies into a single named interface. This is common for \u0026ldquo;Use Case\u0026rdquo; boundaries or library APIs.\ntype LoginCaps = inherit Needs\u0026lt;IUserStore\u0026gt; inherit Needs\u0026lt;IClock\u0026gt; abstract UserStore : IUserStore abstract Clock : IClock let login email : Flow\u0026lt;#LoginCaps, AppError, Session\u0026gt; = flow { let! store = Env\u0026lt;IUserStore\u0026gt; let! clock = Env\u0026lt;IClock\u0026gt; let! user = store.FindByEmail email let! now = clock.UtcNow() return { Email = user; IssuedAt = now } } Using Flexible Types (#) By using the #LoginCaps constraint (the \u0026ldquo;flexible\u0026rdquo; or \u0026ldquo;hash\u0026rdquo; type), this workflow can accept any environment that implements LoginCaps, or even a larger runtime that just happens to satisfy the requirements.\nRunning on a Larger Runtime A runtime can be much larger than the specific cap set the flow asks for.\ntype AppRuntime = { UserStoreService : IUserStore ClockService : IClock LoggerService : ILogger Database : IDatabase } interface LoginCaps with member x.UserStore = x.UserStoreService member x.Clock = x.ClockService interface Needs\u0026lt;IUserStore\u0026gt; with member x.Dep = x.UserStoreService interface Needs\u0026lt;IClock\u0026gt; with member x.Dep = x.ClockService // Even though AppRuntime is huge, it can run the login flow login \u0026#34;ada@example.com\u0026#34; |\u0026gt; Flow.run appRuntime CancellationToken.None Testing Stays Small For tests, you only need to implement the specific caps the flow requires, rather than mocking an entire application record.\ntype TestRuntime = { Clock : IClock } interface Needs\u0026lt;IClock\u0026gt; with member x.Dep = x.Clock getTime |\u0026gt; Flow.run { Clock = MockClock() } CancellationToken.None Next Steps If you want to use simpler record-based environments without interfaces, see the Record Pattern (Environment Slicing) guide.\n","description":"Deep dive into the interface-based CAPS pattern for decoupled dependencies.","linkTitle":"Capabilities (CAPS)","tags":null,"title":"Capabilities (CAPS)","uri":"/docs/managing-dependencies/capabilities/"},{"categories":null,"content":"IcedTasks Integration This page shows how FsFlow can fit beside IcedTasks.\nIcedTasks is a natural neighbor when the codebase already uses task computation expressions and cold or cancellable task helpers.\nFsFlow does not need to replace that layer. It can add typed failure, environment threading, and boundary management where those concerns matter.\nIcedTasks is especially interesting when you want task-native ergonomics and performance-sensitive helpers. FsFlow stays in the picture when you want to carry a typed result and an explicit environment together with the runtime shape.\nShared Ground The overlap is real:\nboth libraries care about task-shaped boundaries both libraries care about delayed execution both libraries care about cancellation-aware execution The difference is the model:\nIcedTasks focuses on task expression ergonomics the task surface focuses on orchestration, typed failure, and a named environment boundary Why The Pair Works IcedTasks keeps the task side fast and ergonomic the task surface keeps the boundary model explicit with Flow\u0026lt;'env, 'error, 'value\u0026gt; the combination works well when you need task-native interop without giving up typed failures or environment/threaded context One naming caveat matters here: IcedTasks uses ColdTask as an alias-style task shape, while the task surface uses a nominal ColdTask\u0026lt;'value\u0026gt; wrapper type. The names are similar, but the types are not interchangeable without an explicit bridge.\nThis page is about coexistence, not a literal side-by-side API sample from both libraries. The code below shows both sides of the boundary, with each bridge made explicit.\nHow To Combine Them Use IcedTasks when the codebase already centers task {} and its adjacent task CE helpers.\nUse Flow when you want:\na typed success/error boundary explicit environment threading ColdTask interop without losing the boundary shape Example The first bridge goes from IcedTasks into FsFlow. Use coldTask when you want delayed execution without a token, and cancellableTask when the helper needs the current CancellationToken:\nopen System.Threading open System.Threading.Tasks open FsFlow open IcedTasks type AppConfig = { Prefix: string } let icedLoadConfig = coldTask { return { Prefix = \u0026#34;Hello\u0026#34; } } let fsFlowUsesIcedTasks : Flow\u0026lt;unit, string, string\u0026gt; = flow { let! config = ColdTask.fromTaskFactory icedLoadConfig return config.Prefix } flow {} auto-binds the ColdTask\u0026lt;'value\u0026gt; wrapper produced by ColdTask.fromTaskFactory icedLoadConfig, so the IcedTasks helper stays cold until the boundary runs. The distinction still matters: icedLoadConfig is an IcedTasks alias-style cold task, while ColdTask\u0026lt;'value\u0026gt; is a nominal wrapper type.\ncoldTask does not take a CancellationToken; it is just unit -\u0026gt; Task\u0026lt;'value\u0026gt;. If the IcedTasks helper needs token flow, use cancellableTask instead:\nlet icedLoadText path = cancellableTask { let! ct = CancellableTask.getCancellationToken () return! System.IO.File.ReadAllTextAsync(path, ct) } The second bridge goes back the other way:\nlet fsGreeting : Flow\u0026lt;unit, string, string\u0026gt; = flow { return \u0026#34;Hello from FsFlow\u0026#34; } let icedTasksUsesFsFlow = cancellableTask { let! ct = CancellableTask.getCancellationToken () let result = Flow.runFull () ct fsGreeting return result } Use Flow.runFull when you want to consume an FsFlow boundary from an IcedTasks computation and pass the current cancellation token through the bridge. Use cancellableTask when you want the IcedTasks side to carry a token through the bridge.\nKeep Started Task Work As Task If you already have started Task work, keep it as Task and bind it directly in flow {}:\nlet started = Task.FromResult 42 let taskBoundary : Flow\u0026lt;unit, string, int\u0026gt; = flow { let! value = started return value } Do not wrap started work in coldTask just to make it look similar. Use Task when the work is already hot, and use coldTask when the helper itself should stay delayed.\nWhen To Prefer IcedTasks Prefer IcedTasks when you mostly need:\nextra task CE variants cold or cancellable task helpers task-native ergonomics without typed orchestration Prefer FsFlow when the boundary itself can carry the environment and typed result shape.\n","description":"How FsFlow fits beside IcedTasks and task-oriented code.","linkTitle":"IcedTasks Integration","tags":null,"title":"IcedTasks Integration","uri":"/docs/ecosystem/integrations-icedtasks/"},{"categories":null,"content":"","description":"","linkTitle":"Patterns","tags":null,"title":"Patterns","uri":"/docs/patterns/"},{"categories":null,"content":"API Reference This categorical index covers the workflow surface, the capability helpers, the pure validation bridge, and the CAPS support packages.\nThe FsFlow ecosystem groups the main public surfaces:\nFlow\u0026lt;'env, 'error, 'value\u0026gt; and the Flow module Capability for named capability helpers and environment access Check for pure Result\u0026lt;'value, unit\u0026gt; predicates Validation for accumulated diagnostics Diagnostics for the structured validation graph Ref for atomic mutable references Schedule for retry and repeat policies STM for software transactional memory Stream for effectful pull-based streams the flow {} and validate {} entry points the CAPS request tokens Needs\u0026lt;'dep\u0026gt; and Env\u0026lt;'dep\u0026gt; / Env\u0026lt;'dep, 'value\u0026gt; for explicit capability boundaries the shared primitives FsFlow.Caps.Core the live capabilities FsFlow.Caps.Console, FileSystem, Http, and Process the host integration FsFlow.Hosting the observability integration FsFlow.Runtime.Telemetry The builder types themselves stay below the surface. The modules are the public story.\nRead the subpages Flow Execution boundaries Type, module, composition, environment, and execution in the flow family.\nCapability Named capability helpers Request tokens, service lookup, and environment/layer composition.\nCheck Pure checks Pure predicates and the bridge to effectful error creation.\nValidation Accumulating validation The Validation type and validate {} builder for collecting diagnostics.\nDiagnostics Structured diagnostics The validation graph and the helpers that render and flatten it.\nRef Atomic references Thread-safe mutable state handles for concurrent workflows.\nSchedule Execution policies DSL for describing retry and repetition strategies.\nSTM Transactional memory Composable atomic transactions across multiple state variables.\nStream Effectful streams Asynchronous, pull-based streams with environment and error support.\nCAPS Core Shared primitives The clock, random, GUID, and environment-variable package.\nCAPS IO System IO Console, FileSystem, HTTP, and Process capability packages.\nHosting Host integration Microsoft.Extensions.DependencyInjection and startup validation.\nTelemetry Observability OpenTelemetry and Activity.trace integration.\n","description":"Module index for the public FsFlow API surface.","linkTitle":"Reference","tags":null,"title":"Reference","uri":"/reference/"},{"categories":null,"content":"STM (Software Transactional Memory) Software Transactional Memory (STM) is a powerful concurrency primitive that allows you to combine multiple atomic operations into a single transaction.\nWhile Ref is perfect for updating a single variable, STM is designed for scenarios where you need to update multiple variables consistently. FsFlow ensures that the entire transaction is executed atomically—either all changes are committed, or none are.\nNote: STM is currently available on .NET only.\nCore Concepts TRef\u0026lt;'T\u0026gt;: A transactional reference. Similar to Ref\u0026lt;'T\u0026gt;, but designed to be used inside an STM transaction. stm { ... }: A computation expression used to compose transactional operations. STM.atomically: The bridge that executes an stm block as a single atomic effect within a flow. Basic Usage Defining a Transaction Transactions are defined using the stm {} builder. You can read, write, and update multiple TRef values within a single block.\nlet transferFunds (fromAcc: TRef\u0026lt;decimal\u0026gt;) (toAcc: TRef\u0026lt;decimal\u0026gt;) (amount: decimal) = stm { let! currentFrom = TRef.get fromAcc do! TRef.set (currentFrom - amount) fromAcc do! TRef.update (fun balance -\u0026gt; balance + amount) toAcc } Running the Transaction To execute an stm block, you use STM.atomically. This turns the transaction into a standard Flow.\nlet processTransfer fromAcc toAcc amount = flow { // Run the transaction atomically do! STM.atomically (transferFunds fromAcc toAcc amount) printfn \u0026#34;Transfer complete!\u0026#34; } Composition STM transactions are first-class values. You can compose multiple small transactions into a larger one using stm {} before ever calling atomically. This is the \u0026ldquo;Software\u0026rdquo; in STM—it allows for modular, composable concurrency.\nlet deposit (acc: TRef\u0026lt;decimal\u0026gt;) (amount: decimal) = TRef.update (fun x -\u0026gt; x + amount) acc let batchTransfer acc1 acc2 acc3 amount = stm { // Composite transaction do! transferFunds acc1 acc2 amount do! deposit acc3 (amount / 2.0m) } |\u0026gt; STM.atomically Why use STM instead of Lock? Using lock manually is error-prone and can lead to deadlocks if different parts of your code acquire multiple locks in a different order. STM eliminates deadlocks by managing a consistent commit order internally and makes complex state transitions much easier to write and maintain.\nAPI Reference: Module TRef Function Signature Description make 'T -\u0026gt; STM\u0026lt;TRef\u0026lt;'T\u0026gt;\u0026gt; Creates a new transactional reference. get TRef\u0026lt;'T\u0026gt; -\u0026gt; STM\u0026lt;'T\u0026gt; Reads the value of a TRef within a transaction. set 'T -\u0026gt; TRef\u0026lt;'T\u0026gt; -\u0026gt; STM\u0026lt;unit\u0026gt; Sets the value of a TRef within a transaction. update ('T -\u0026gt; 'T) -\u0026gt; TRef\u0026lt;'T\u0026gt; -\u0026gt; STM\u0026lt;unit\u0026gt; Atomically updates a TRef within a transaction. API Reference: Module STM Function Signature Description atomically STM\u0026lt;'T\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'none, 'T\u0026gt; Executes a composed transaction as an atomic flow. ","description":"Composable atomic transactions across multiple variables in FsFlow.","linkTitle":"STM (Software Transactional Memory)","tags":null,"title":"STM (Software Transactional Memory)","uri":"/docs/state-concurrency/stm/"},{"categories":null,"content":"Straightforward Examples These examples show how to use FsFlow for common tasks without the overhead of a full application setup.\n1. Simple Environment Access Use Flow.read to project a single field from your environment record.\ntype Config = { ApiUrl: string } let getUrl = flow { let! url = Flow.read _.ApiUrl return url } let outcome = getUrl |\u0026gt; Flow.run { ApiUrl = \u0026#34;https://api.example.com\u0026#34; } // outcome = Exit.Success \u0026#34;https://api.example.com\u0026#34; 2. Combining Pure Logic and Async Work Use flow {} to mix pure Check logic, Async blocks, and other flows.\nlet validateId id = id |\u0026gt; okIf (id \u0026gt; 0) |\u0026gt; orError \u0026#34;Invalid ID\u0026#34; let fetchUser id = async { return { Id = id; Name = \u0026#34;Ada\u0026#34; } } let workflow id = flow { let! validId = validateId id let! user = fetchUser validId // Binds Async\u0026lt;\u0026#39;T\u0026gt; directly return user.Name } let effect = workflow 42 |\u0026gt; Flow.run () // effect = Effect\u0026lt;string, string\u0026gt; (ValueTask or Async) 3. Retrying a Flow Use the Schedule module to add operational policies like retries.\nlet flakyTask = flow { // Imagine this calls a flaky API return! Task.FromResult (Ok \u0026#34;Success\u0026#34;) } let resilientWorkflow = flakyTask |\u0026gt; Flow.Retry (Schedule.recurs 3) [`Flow.Retry`](/reference/schedule/m-flowscheduleextensions-flow-retry-static/) will retry up to 3 times if the task fails. 4. Conditional Execution Since flow {} is a standard F# computation expression, you can use if/then, match, and try/with inside it.\nlet conditionalWorkflow input = flow { if String.IsNullOrWhiteSpace input then return \u0026#34;No input provided\u0026#34; else let! processed = processInput input return processed } 5. Mapping Errors Use Flow.mapError to translate low-level technical errors into domain-specific failures.\ntype AppError = DatabaseUnavailable | UserNotFound let domainWorkflow = lowLevelFlow |\u0026gt; Flow.mapError (function | DbException _ -\u0026gt; DatabaseUnavailable | :? KeyNotFoundException -\u0026gt; UserNotFound | _ -\u0026gt; DatabaseUnavailable) ","description":"Quick, practical examples of FsFlow in action.","linkTitle":"Straightforward Examples","tags":null,"title":"Straightforward Examples","uri":"/docs/start/basic-examples/"},{"categories":null,"content":"Task and Async Interop FsFlow provides a single, unified computation expression—flow {}—that handles synchronous code, F# Async, and .NET Task interop natively. You don\u0026rsquo;t have to choose between different builders; the same flow can orchestrate all these effect types.\nDirect Binds Inside a flow {} block, you can use let! to bind many common F# and .NET types directly. FsFlow handles the conversion to its internal execution model automatically.\nType Outcome Flow\u0026lt;'env, 'error, 'value\u0026gt; Continues with the flow\u0026rsquo;s value. Result\u0026lt;'value, 'error\u0026gt; Continues on Ok, short-circuits on Error. Async\u0026lt;'value\u0026gt; Awaits the async and continues with the value. Async\u0026lt;Result\u0026lt;'value, 'error\u0026gt;\u0026gt; Awaits the async and handles the Result outcome. Task\u0026lt;'value\u0026gt; Awaits the task and continues with the value. Task\u0026lt;Result\u0026lt;'value, 'error\u0026gt;\u0026gt; Awaits the task and handles the Result outcome. ValueTask\u0026lt;'value\u0026gt; Awaits the value task and continues with the value. ValueTask\u0026lt;Result\u0026lt;'value, 'error\u0026gt;\u0026gt; Awaits and handles the Result outcome. Example: Mixed Orchestration let fetchUser (id: int) : Task\u0026lt;User\u0026gt; = ... let validate (user: User) : Result\u0026lt;User, string\u0026gt; = ... let saveUser (user: User) : Async\u0026lt;unit\u0026gt; = ... let processUser id = flow { // Bind a .NET Task let! user = fetchUser id // Bind a Result let! validUser = validate user // Bind an F# Async do! saveUser validUser return \u0026#34;Done\u0026#34; } Option and ValueOption Option\u0026lt;'value\u0026gt; and ValueOption\u0026lt;'value\u0026gt; can also be bound directly, but only if the flow\u0026rsquo;s error type is unit.\nlet maybeValue = Some 42 let workflow : Flow\u0026lt;unit, unit, int\u0026gt; = flow { let! x = maybeValue // Binds directly because error is unit return x } If you need a specific error when an option is None, use Flow.fromOption:\nlet workflow : Flow\u0026lt;unit, string, int\u0026gt; = flow { let! x = maybeValue |\u0026gt; Flow.fromOption \u0026#34;Value was missing\u0026#34; return x } Hot vs. Cold Work Understanding the difference between \u0026ldquo;Hot\u0026rdquo; and \u0026ldquo;Cold\u0026rdquo; work is crucial for correct execution and cancellation behavior.\nHot Work (Started Tasks) Types like Task\u0026lt;'T\u0026gt; and ValueTask\u0026lt;'T\u0026gt; are Hot. The work might already be running before you bind it.\nRerunning the flow re-awaits the same underlying work. You cannot pass the flow\u0026rsquo;s runtime CancellationToken into work that has already started. Cold Work (Flows and ColdTask) Flow itself and the ColdTask\u0026lt;'T\u0026gt; type are Cold. The work only starts when the flow is executed by Flow.run.\nRerunning the flow repeats the work from scratch. The runtime CancellationToken is automatically passed into the work. Using ColdTask\u0026lt;'T\u0026gt; ColdTask\u0026lt;'T\u0026gt; is a simple wrapper: CancellationToken -\u0026gt; Task\u0026lt;'T\u0026gt;. It allows you to define task-based work that remains lazy and cancellation-aware.\nlet loadData path = ColdTask(fun ct -\u0026gt; File.ReadAllTextAsync(path, ct)) let myFlow = flow { let! text = loadData \u0026#34;info.txt\u0026#34; return text } Guard: Bridging with Error Packaging When you have a source that already contains an error (like Async\u0026lt;Result\u0026lt;_,_\u0026gt;\u0026gt; or Task\u0026lt;Option\u0026lt;_\u0026gt;\u0026gt;), and you want to bind it while providing or mapping the error, use Guard.\nlet guardedTask = Guard.Of(\u0026#34;missing\u0026#34;, Task.FromResult(None)) let myFlow = flow { let! value = guardedTask // Binds and fails with \u0026#34;missing\u0026#34; if None return value } Summary Use flow {} for all application orchestration. Prefer direct binding for Async, Task, and Result. Use ColdTask for task-based logic that should respect flow cancellation, retry, and repetition. Use Guard to bridge existing error-bearing sources with custom error mapping. Next Read Execution Semantics for the exact runtime behavior, or Managing Dependencies for structuring your environment.\n","description":"Direct binding rules for async and task work in FsFlow.","linkTitle":"Task and Async Interop","tags":null,"title":"Task and Async Interop","uri":"/docs/core-model/task-async-interop/"},{"categories":null,"content":"Validate CE Use the validate {} computation expression when you have multiple independent checks and you want to collect every failure into a single report.\nWhile the standard result {} or flow {} blocks \u0026ldquo;fail fast\u0026rdquo; (stopping at the first error), validate {} continues checking even after a failure occurs. This is often called \u0026ldquo;accumulating\u0026rdquo; semantics.\nAccumulating with and! The key to accumulation is the and! keyword. Steps joined by and! are evaluated independently, and their errors are merged into a Diagnostics graph.\nopen FsFlow.Check type Registration = { Name: string; Email: string } type RegError = NameRequired | EmailRequired let validateRegistration input = validate { let! name = input.Name |\u0026gt; notBlank |\u0026gt; orError NameRequired and! email = input.Email |\u0026gt; notBlank |\u0026gt; orError EmailRequired return { Name = name; Email = email } } let outcome = validateRegistration { Name = \u0026ldquo;\u0026rdquo;; Email = \u0026quot;\u0026quot; } // outcome = Validation (Error { // Errors = [NameRequired; EmailRequired] // Children = [] // })\nIf both fields are blank, the result contains a `Diagnostics` object with both `NameRequired` and `EmailRequired`. ## Sequential Steps in `validate {}` Standard `let!` and `do!` inside a `validate {}` block still short-circuit. This is useful for \u0026#34;gate\u0026#34; checks that must pass before other validation can proceed. ```fsharp validate { // Stop immediately if the whole object is null let! input = input |\u0026gt; notNull |\u0026gt; orError ObjectMissing // These run only if input was not null, but they run independently of each other let! name = input.Name |\u0026gt; notBlank |\u0026gt; orError NameRequired and! email = input.Email |\u0026gt; notBlank |\u0026gt; orError EmailRequired return { Name = name; Email = email } } Relationship with Result Validation\u0026lt;'value, 'error\u0026gt; is structurally similar to Result\u0026lt;'value, Diagnostics\u0026lt;'error\u0026gt;\u0026gt;. You can convert between them easily:\nUse Validation.toResult to get a standard result back. Use Result.toValidation to start an accumulating block from an existing result. In general, use validate {} at the \u0026ldquo;leaves\u0026rdquo; of your application (like form parsing) and flow {} for the \u0026ldquo;branches\u0026rdquo; (the main business logic).\nNested Scopes To build a structured report (e.g., for JSON APIs), use the validate.key, validate.index, and validate.name helpers. These prefix any diagnostics produced inside the block.\nlet validateCustomer customer = validate.key \u0026#34;customer\u0026#34; { let! name = validate.name \u0026#34;Name\u0026#34; { return! customer.Name |\u0026gt; notBlank |\u0026gt; orError \u0026#34;Required\u0026#34; } return name } let v = validateCustomer { Name = \u0026#34;\u0026#34; } // v = Validation (Error { // Errors = [] // Children = [ // Key \u0026#34;customer\u0026#34; -\u0026gt; { // Errors = [] // Children = [ // Name \u0026#34;Name\u0026#34; -\u0026gt; { Errors = [\u0026#34;Required\u0026#34;]; Children = [] } // ] // } // ] // }) Using Diagnostics.toString v would render:\ncustomer: Name: - Required When to use validate {} Forms and User Input: Where the user wants to see all errors at once. Complex Documents: Where you need to point failures back to specific paths or indices. Independent Rules: When rules can be checked in any order. To learn more about the structure of the accumulated errors, see Diagnostics Graph.\n","description":"Accumulating validation with the validate { } builder.","linkTitle":"Validate CE","tags":null,"title":"Validate CE","uri":"/docs/validation-results/validate-ce/"},{"categories":null,"content":"Architectural Styles This page shows how the FsFlow workflow family should fit into your application architecture without forcing one app shape on every codebase.\nFsFlow supports three valid architectural styles.\nThree related workflow families. Three valid architectural styles. Choose based on app shape and team preferences.\n1. Booted App Environment Use this when your application already has a conventional booted runtime and passing one explicit application environment keeps composition simple.\nThis is the most direct use of the Record Pattern. The environment is the full booted application runtime and config:\nDB logging config clients services cache Typical shape:\ntype AppEnv = { Db: IDb Log: string -\u0026gt; unit Config: AppConfig Billing: IBillingClient Cache: ICache } let handle command : Flow\u0026lt;AppEnv, AppError, ResultValue\u0026gt; = flow { let! env = Flow.env env.Log \u0026#34;handling command\u0026#34; return! runWorkflow env.Db env.Billing command } This is inspired by app-level runtime shapes such as Rails, Phoenix, or a booted .NET host, but the environment is still passed explicitly and never global.\nUse this style for:\ncontrollers and endpoints handlers persistence workflows infrastructure-heavy orchestration integration tests Choose this when simplicity of app composition matters most.\n2. Explicit Dependencies Plus Context Use this when you want feature modules to state their real dependencies directly and keep 'ctx for request or execution context only.\nTypical shape:\ntype PlaceOrderDeps = { LoadCart: CartId -\u0026gt; Flow\u0026lt;RequestContext, AppError, Cart\u0026gt; SaveOrder: Order -\u0026gt; Flow\u0026lt;RequestContext, AppError, unit\u0026gt; PublishEvent: OrderPlaced -\u0026gt; Flow\u0026lt;RequestContext, AppError, unit\u0026gt; } type RequestContext = { TraceId: string UserId: string Deadline: System.DateTimeOffset } let placeOrder (deps: PlaceOrderDeps) (input: PlaceOrderInput) : Flow\u0026lt;RequestContext, AppError, OrderId\u0026gt; = flow { let! ctx = Flow.env let! cart = deps.LoadCart input.CartId let order = Order.create ctx.UserId cart do! deps.SaveOrder order do! deps.PublishEvent (OrderPlaced order.Id) return order.Id } The shape is:\ndeps -\u0026gt; input -\u0026gt; Flow\u0026lt;\u0026#39;ctx, \u0026#39;err, \u0026#39;a\u0026gt; Here, the Record Pattern is used only for the thin 'ctx (request or execution context). Typical examples:\ntrace id request id user or session cancellation deadline Use this style for:\nuse cases domain orchestration workflow modules highly testable feature logic Choose this when clarity and locality matter most.\n3. Standard .NET AppHost Plus DI Use this when the surrounding application should stay in standard .NET startup and dependency injection, and FsFlow should only appear inside workflow code.\nKeep the host conventional:\nAppHost DI container logging, config, and options normal .NET startup Use FsFlow inside:\nfeature workflows handlers jobs application services Typical shape:\ntype RuntimeServices = { Logger: ILogger\u0026lt;ShipOrderWorkflow\u0026gt; } type AppEnv = { Gateway: IShippingGateway } type ShipOrderWorkflow() = member _.Run(input: ShipOrderInput) : Flow\u0026lt;RuntimeContext\u0026lt;RuntimeServices, AppEnv\u0026gt;, AppError, ShipmentId\u0026gt; = flow { let! logger = Flow.readRuntime _.Logger let! gateway = Flow.read _.Gateway logger.LogInformation(\u0026#34;shipping order {OrderId}\u0026#34;, input.OrderId) let! shipmentId = gateway.CreateShipment(input.OrderId) return shipmentId } This style often utilizes the CAPS Pattern to bridge existing .NET services into a decoupled FsFlow contract.\nUse this style for:\nmixed C# and F# teams enterprise .NET apps incremental adoption Choose this when familiarity and low migration risk matter most.\nIf the task boundary needs separate runtime services and application capabilities, use RuntimeContext\u0026lt;'runtime, 'env\u0026gt; and the Flow.readRuntime / Flow.read split instead of forcing everything into one record.\nWhich Style To Prefer There is no single mandated architecture.\nUse Booted App Environment when app-level composition is the main concern. Use Explicit Dependencies Plus Context when feature-level reasoning and testability matter more. Use standard .NET AppHost plus DI when the host should stay conventional and the workflow family is an internal application abstraction. The important constraint is not which style you pick. The important constraint is that the chosen workflow family stays explicit at the workflow boundary and at execution time.\nNext Read docs/GETTING_STARTED.md for the core workflow model, docs/ENV_SLICING.md for smaller environment projections, and docs/WHY_FSFLOW.md for the trade-offs against manual threading and wrapper-based shapes.\n","description":"","linkTitle":"Architectural Styles","tags":null,"title":"Architectural Styles","uri":"/docs/core-model/architectural-styles/"},{"categories":null,"content":"This page shows the source-documented Check surface: the unit-failure result type and reusable predicate helpers.\nCore type FsFlow.Check: A reusable predicate result that either preserves a value on success or acts as a gate with unit on success, while carrying a unit failure placeholder until the caller maps it into a domain-specific error. Module functions FsFlow.CheckModule.fromPredicate: Builds a check from a predicate while preserving the successful value. FsFlow.CheckModule.not: Returns success when the supplied check fails. FsFlow.CheckModule.and: Returns success when both checks succeed. FsFlow.CheckModule.or: Returns success when either check succeeds. FsFlow.CheckModule.all: Returns success when every check in the sequence succeeds. FsFlow.CheckModule.any: Returns success when at least one check in the sequence succeeds. FsFlow.CheckModule.okIf: Returns success when the condition is true. FsFlow.CheckModule.failIf: Returns success when the condition is false. FsFlow.CheckModule.okIfSome: Returns the value when the option is Some. FsFlow.CheckModule.okIfNone: Returns success when the option is None. FsFlow.CheckModule.failIfSome: Returns success when the option is None. FsFlow.CheckModule.failIfNone: Returns the value when the option is Some. FsFlow.CheckModule.okIfValueSome: Returns the value when the value option is ValueSome. FsFlow.CheckModule.okIfValueNone: Returns success when the value option is ValueNone. FsFlow.CheckModule.failIfValueSome: Returns success when the value option is ValueNone. FsFlow.CheckModule.failIfValueNone: Returns the value when the value option is ValueSome. FsFlow.CheckModule.okIfNotNull: Returns the value when it is not null. FsFlow.CheckModule.okIfNull: Returns success when the value is null. FsFlow.CheckModule.failIfNotNull: Returns success when the value is null. FsFlow.CheckModule.failIfNull: Returns the value when it is null. FsFlow.CheckModule.okIfNotEmpty: Returns the sequence when it is not empty. FsFlow.CheckModule.okIfEmpty: Returns success when the sequence is empty. FsFlow.CheckModule.failIfNotEmpty: Returns success when the sequence is empty. FsFlow.CheckModule.failIfEmpty: Returns the sequence when it is not empty. FsFlow.CheckModule.okIfEqual: Returns success when the values are equal. FsFlow.CheckModule.okIfNotEqual: Returns success when the values are not equal. FsFlow.CheckModule.failIfEqual: Returns success when the values are equal. FsFlow.CheckModule.failIfNotEqual: Returns success when the values are not equal. FsFlow.CheckModule.okIfNonEmptyStr: Returns the string when it is not null or empty. FsFlow.CheckModule.okIfEmptyStr: Returns success when the string is null or empty. FsFlow.CheckModule.failIfNonEmptyStr: Returns success when the string is null or empty. FsFlow.CheckModule.failIfEmptyStr: Returns the string when it is null or empty. FsFlow.CheckModule.okIfNotBlank: Returns the string when it is not blank. FsFlow.CheckModule.notBlank: Returns the string when it is not blank. FsFlow.CheckModule.okIfBlank: Returns success when the string is blank. FsFlow.CheckModule.blank: Returns success when the string is blank. FsFlow.CheckModule.failIfNotBlank: Returns success when the string is blank. FsFlow.CheckModule.failIfBlank: Returns the string when it is blank. FsFlow.CheckModule.orError: Maps a unit error into the supplied application error value. FsFlow.CheckModule.orErrorWith: Maps a unit error into an application error produced on demand. FsFlow.CheckModule.notNull: Returns the value when it is not null. FsFlow.CheckModule.notEmpty: Returns the sequence when it is not empty. FsFlow.CheckModule.equal: Returns success when the values are equal. FsFlow.CheckModule.notEqual: Returns success when the values are not equal. ","description":"","linkTitle":"Check","tags":null,"title":"Check","uri":"/reference/check/"},{"categories":null,"content":"Diagnostics Graph Unlike many validation libraries that return a flat list of error strings, FsFlow returns a structured Diagnostics Graph. This allows you to represent exactly where in a complex data structure a failure occurred.\nThe Structure The graph is a tree where each node can contain local errors and child branches.\ntype PathSegment = | Key of string // A record field or property | Index of int // A position in a list or sequence | Name of string // A custom label for a validation branch type Diagnostic\u0026lt;\u0026#39;error\u0026gt; = { Path: PathSegment list Error: \u0026#39;error } type Diagnostics\u0026lt;\u0026#39;error\u0026gt; = { Errors: \u0026#39;error list Children: Map\u0026lt;PathSegment, Diagnostics\u0026lt;\u0026#39;error\u0026gt;\u0026gt; } Creating Scoped Diagnostics Inside a validate {} block, you use helpers to push diagnostics into the tree:\nvalidate.key \u0026quot;address\u0026quot; -\u0026gt; Failures appear under .address validate.index 0 -\u0026gt; Failures appear under .[0] validate.name \u0026quot;Shipping\u0026quot; -\u0026gt; Failures appear under .Shipping let validateAddress addr = validate.key \u0026#34;address\u0026#34; { let! city = validate.name \u0026#34;City\u0026#34; { ... } return ... } Consuming Diagnostics Once you have a Validation\u0026lt;'v, 'e\u0026gt; result, you can transform the graph for the user:\n1. Flattening for APIs Use Diagnostics.flatten to turn the tree into a flat list of path-bearing errors. This is the standard pattern for JSON APIs.\n// Path: [Key \u0026#34;customer\u0026#34;; Key \u0026#34;address\u0026#34;; Name \u0026#34;City\u0026#34;] // Error: \u0026#34;Required\u0026#34; // Flat: \u0026#34;customer.address.City: Required\u0026#34; 2. Human-Readable Output Use Diagnostics.toString to render the graph as a compact, YAML-like tree. This is great for logs or console output.\ncustomer: address: City: - Required Mapping and Filtering Diagnostics are generic over the 'error type. You can use Validation.mapError (or Diagnostics.map directly) to translate internal domain errors into user-facing localized strings at the application boundary.\nSee it in Action For a complete, runnable example that demonstrates nested validation, path rendering, and JSON API error formatting, see the Diagnostics Example in the runnable examples gallery.\nYou can also view the source code directly on GitHub.\n","description":"Deep dive into the structured error reporting system.","linkTitle":"Diagnostics Graph","tags":null,"title":"Diagnostics Graph","uri":"/docs/validation-results/diagnostics/"},{"categories":null,"content":"","description":"","linkTitle":"Ecosystem","tags":null,"title":"Ecosystem","uri":"/docs/ecosystem/"},{"categories":null,"content":"FSharpPlus Integration This page shows how FsFlow can fit beside codebases that already use FSharpPlus.\nFSharpPlus is a broad functional base library. That makes it different from the more targeted integration stories like FsToolkit.ErrorHandling, Validus, and IcedTasks.\nFsFlow can sit on top of that style where orchestration begins.\nFSharpPlus is strongest when the codebase already relies on broad generic operations and monad transformer stacks. That strength comes with a cost: more compiler work, more abstraction to keep in your head, and error surfaces that can be harder to read when you are trying to understand a FsFlow boundary.\nKeep The Boundary Clear Good separation looks like this:\nuse FSharpPlus for the generic functional helpers and abstractions the codebase already trusts use FsFlow for explicit execution, environment threading, and typed failure This makes FsFlow the boundary model and keeps FSharpPlus focused on the general-purpose helpers it already does well.\nThat keeps the surface coherent and avoids turning one function into a stack of overlapping abstractions.\nHow To Combine Them Typical coexistence patterns:\nkeep pure transformations in FSharpPlus use FsFlow to sequence those transformations against a runtime boundary let FsFlow own the Flow boundary at the edge The practical rule is: if the code is generic and reusable across many domains, FSharpPlus can own it. If the code is choosing the runtime shape, the environment, or the typed failure boundary, FsFlow can own it.\nExample Keep the reusable helper separate from the boundary:\ntype AppEnv = { Prefix: string Name: string } let normalizeName name = name.Trim() let buildGreeting prefix name = $\u0026#34;{prefix} {normalizeName name}\u0026#34; let greet : Flow\u0026lt;AppEnv, string, string\u0026gt; = flow { let! prefix = Flow.read _.Prefix let! name = Flow.read _.Name return buildGreeting prefix name } If you already use FSharpPlus for generic mapping or chaining, keep that code in the helper layer and let FsFlow read the environment at the edge.\nThe same helper can sit under an async boundary without changing its shape:\nlet greetAsync : Flow\u0026lt;AppEnv, string, string\u0026gt; = flow { let! prefix = Flow.read _.Prefix let! name = Flow.read _.Name return buildGreeting prefix name } The generic helper remains generic, but the boundary is FsFlow.\nWhen To Prefer FsFlow Over More Generic Abstractions Prefer FsFlow when the concern is:\nthe runtime boundary explicit environment access typed failure honest task/async/sync distinction Prefer FSharpPlus when the concern is a reusable generic functional helper that can stay independent of a particular family.\n","description":"How FsFlow fits beside FSharpPlus-based codebases.","linkTitle":"FSharpPlus Integration","tags":null,"title":"FSharpPlus Integration","uri":"/docs/ecosystem/integrations-fsharpplus/"},{"categories":null,"content":"Managing Dependencies In FsFlow, a workflow is not just a function; it is a description of work that needs an environment to run.\nAs your application grows, you might be tempted to create a single \u0026ldquo;God Object\u0026rdquo; (like AppEnv) that contains every service in your system: Database, Logger, API Gateways, and more. However, if every small workflow depends on this massive record, your code becomes hard to test and tightly coupled. You\u0026rsquo;d have to mock the entire universe just to test a simple calculation.\nFsFlow provides two primary architectural styles to help you \u0026ldquo;slice\u0026rdquo; your dependencies so that each workflow only asks for what it actually needs.\nThe Two Styles 1. The Record Pattern (Environment Slicing) This is the simplest way to start. You define your environment as a standard F# record. Workflows \u0026ldquo;read\u0026rdquo; or \u0026ldquo;project\u0026rdquo; the fields they need from this record. It is perfect for local helpers, internal logic, and smaller applications where record types are stable.\nRead the Deep Dive: Environment Slicing\n2. The CAPS Pattern (Decoupled Capabilities) This style decouples your workflows from specific record types using interface-based contracts. A workflow says \u0026ldquo;I need a clock,\u0026rdquo; and it doesn\u0026rsquo;t care if that clock comes from a massive app runtime or a tiny test object. It is the best choice for public APIs, shared libraries, and large-scale systems.\nRead the Deep Dive: Capabilities (CAPS)\nRelationship to Architecture These two patterns support different Architectural Styles:\nStyle 1: The Booted App: Usually uses a single large record (Record Pattern) for simplicity. Style 2: Parameters + Context: Uses parameters for core logic and a thin record (Record Pattern) for request context. Style 3: .NET DI: Often uses the CAPS Pattern to bridge .NET services into the FsFlow execution model. For more details on these structures, see Architectural Styles.\nComparison at a Glance Feature Record Pattern CAPS Pattern Typical Use Local helpers, small apps Public APIs, shared libraries Coupling Bound to a specific record type Bound to an interface/contract Simplicity High (Standard F#) Medium (Interface-based) Flexibility Moderate Very High Which style should I use? Start with the Record Pattern. It is the most idiomatic way to write F# and requires the least amount of boilerplate.\nMove to the CAPS Pattern when:\nYou are building a library that others will consume. You find yourself writing complex \u0026ldquo;shim\u0026rdquo; records just to run a workflow in a different context. You want your workflows to read like a set of required \u0026ldquo;Capabilities\u0026rdquo; rather than a set of record fields. Shared Helpers: The Capability Module Regardless of which style you choose, FsFlow provides a Capability module that works across both. These helpers let you read from the main Flow surface and from RuntimeContext without needing specific module prefixes.\nlet log message = flow { let! logger = Capability.service _.Logger logger.Log message } Learn more about these polymorphic helpers in the Environment Slicing guide.\n","description":"Introduction to dependency management in FsFlow.","linkTitle":"Managing Dependencies","tags":null,"title":"Managing Dependencies","uri":"/docs/managing-dependencies/"},{"categories":null,"content":"Stream (FlowStream) FlowStream\u0026lt;'env, 'error, 'value\u0026gt; represents a cold, pull-based asynchronous stream. Like Flow, a FlowStream requires an environment to run and can fail with a typed error. It is built on top of .NET\u0026rsquo;s IAsyncEnumerable, providing native support for backpressure and asynchronous iteration.\nNote: FlowStream is currently available on .NET only.\nCreating a Stream From a Sequence The simplest way to create a stream is from an existing seq.\nlet numbers = FlowStream.fromSeq [ 1 .. 10 ] Transforming Streams Mapping Values You can transform the successful values in a stream using FlowStream.map.\nlet doubled = numbers |\u0026gt; FlowStream.map (fun x -\u0026gt; x * 2) Consuming Streams To consume a stream, you use one of the execution helpers. These helpers turn the stream into a Flow that you can then run or compose.\nrunForEach Executes an action for every successful value in the stream. If the stream encounters a failure, execution stops and the Flow returns that failure.\nlet printNumbers = FlowStream.runForEach () (printfn \u0026#34;Value: %d\u0026#34;) numbers Why use FlowStream? FlowStream is designed for scenarios where you need to process large amounts of data without loading everything into memory at once. Because it is part of the FsFlow family, it integrates perfectly with your existing environments, errors, and cancellation logic.\nEnvironment-Aware: Can read dependencies like databases or APIs during iteration. Typed Failures: Handles errors consistently with the rest of your application. Cancellable: Automatically respects the CancellationToken provided to Flow.run. API Reference: Module FlowStream Function Signature Description fromSeq seq\u0026lt;'v\u0026gt; -\u0026gt; FlowStream\u0026lt;'e, 'err, 'v\u0026gt; Creates a stream from a synchronous sequence. map ('v -\u0026gt; 'w) -\u0026gt; FlowStream\u0026lt;'e, 'err, 'v\u0026gt; -\u0026gt; FlowStream\u0026lt;'e, 'err, 'w\u0026gt; Transforms the values in the stream. runForEach 'env -\u0026gt; ('v -\u0026gt; unit) -\u0026gt; FlowStream\u0026lt;'e, 'err, 'v\u0026gt; -\u0026gt; Flow\u0026lt;'env, 'err, unit\u0026gt; Consumes the stream with a side-effecting action. Next Steps Explore more advanced concurrency patterns in State and Concurrency.\n","description":"Effectful, pull-based asynchronous streams in FsFlow.","linkTitle":"Stream (FlowStream)","tags":null,"title":"Stream (FlowStream)","uri":"/docs/state-concurrency/stream/"},{"categories":null,"content":"Effect-TS Comparison This page shows FsFlow in relation to Effect-TS without pretending they solve the same problem at the same scale.\nWhat Carries Over These ideas are shared:\ntyped success and error channels explicit dependency access compositional workflow values runtime helpers for retry, timeout, and cancellation-aware execution What Is Different FsFlow is aimed at ordinary F# application code:\nflow {} instead of generator-based syntax, with direct binding for Async, Task, ValueTask, and ColdTask first-class interop with Result, Async, and .NET Task explicit environment reads such as Flow.read _.Gateway or Flow.read _.Gateway a much smaller surface focused on application flows rather than a broader runtime platform What Effect-TS Still Has That FsFlow Does Not Effect-TS is much broader and more mature. FsFlow does not try to match:\na richer service and context system structured concurrency runtime features broader runtime primitives such as streams and channels integrated observability tooling a large package ecosystem Practical Comparison The useful question for F# users is not \u0026ldquo;how close is this to Effect-TS?\u0026rdquo;\nThe useful questions are:\nis this clearer than Async\u0026lt;Result\u0026lt;_,_\u0026gt;\u0026gt; for the flows you actually write? do explicit env requirements help enough to justify the abstraction? does the workflow-family split make mixed sync, Async, and .NET Task code easier to keep readable? Practical Takeaway Use FsFlow if you want a small F#-native library for composable flows with explicit dependencies, typed failures, explicit cancellation, and direct .NET interop.\nDo not evaluate it as a feature-peer to Effect-TS. Evaluate it against the F# code you would otherwise write.\nNext If you are deciding whether to adopt the library, read docs/GETTING_STARTED.md, docs/TASK_ASYNC_INTEROP.md, and docs/examples/README.md.\n","description":"Where FsFlow overlaps with Effect-TS and where it stays intentionally smaller.","linkTitle":"Effect-TS Comparison","tags":null,"title":"Effect-TS Comparison","uri":"/docs/ecosystem/effect-ts-comparison/"},{"categories":null,"content":"State and Concurrency FsFlow provides several primitives for managing shared state and coordinating concurrent workflows. These tools allow you to build complex, highly-available systems while maintaining the benefits of a Result-based model.\nOverview Ref (Atomic References) Ref\u0026lt;'T\u0026gt; provides a thread-safe handle for mutable state. It is perfect for shared counters, flags, or small pieces of state that need to be updated atomically across multiple fibers.\nSchedule (Retries \u0026amp; Repetition) The Schedule module provides a powerful language for describing how and when a workflow should be retried upon failure or repeated upon success.\nSTM (Software Transactional Memory) STM allows you to compose multiple atomic operations on TVar (transactional variables) into a single transaction. It provides ACID-like properties for in-memory state.\nStream (FlowStream) FlowStream is an effectful, pull-based stream. It allows you to process large amounts of data asynchronously while respecting the FsFlow environment and error model.\n","description":"Shared state, coordination, and streaming in FsFlow.","linkTitle":"State and Concurrency","tags":null,"title":"State and Concurrency","uri":"/docs/state-concurrency/"},{"categories":null,"content":"This page shows the source-documented Validation surface: the accumulating result type, module functions, and path-scoping helpers.\nCore type FsFlow.Validation: An accumulating validation result that keeps the structured diagnostics graph visible. Module functions FsFlow.ValidationModule.toResult: Converts a Validation into a standard Result. FsFlow.ValidationModule.ok: Creates a successful validation result. FsFlow.ValidationModule.error: Creates a failing validation result with the provided diagnostics. FsFlow.ValidationModule.succeed: Alias for ok. FsFlow.ValidationModule.fail: Alias for error. FsFlow.ValidationModule.fromResult: Lifts a standard Result into the Validation context. FsFlow.ValidationModule.map: Maps the successful value of a validation. FsFlow.ValidationModule.bind: Sequences a validation-producing continuation. FsFlow.ValidationModule.mapError: Maps the error type of a validation graph. FsFlow.ValidationModule.map2: Combines two validations, accumulating errors if both fail. FsFlow.ValidationModule.map3: Combines three validations, accumulating errors when any input fails. FsFlow.ValidationModule.apply: Applies a validation-wrapped function to a validation-wrapped value. FsFlow.ValidationModule.ignore: Maps a successful validation value to unit while preserving the diagnostics. FsFlow.ValidationModule.orElse: Falls back to another validation when the source validation fails. FsFlow.ValidationModule.orElseWith: Computes a fallback validation from the source diagnostics when validation fails. FsFlow.ValidationModule.collect: Collects a sequence of validations into a single validation of a list. FsFlow.ValidationModule.sequence: Transforms a sequence of validations into a validation of a list. FsFlow.ValidationModule.traverseIndexed: Maps a sequence into validations while prefixing each item with its index. FsFlow.ValidationModule.merge: Merges two validations into a validation of a tuple. Path scoping FsFlow.ValidationModule.at: Scopes a validation under the supplied path segments. FsFlow.ValidationModule.key: Prefixes a validation with a keyed branch. FsFlow.ValidationModule.index: Prefixes a validation with an indexed branch. FsFlow.ValidationModule.name: Prefixes a validation with a named branch. ","description":"","linkTitle":"Validation","tags":null,"title":"Validation","uri":"/reference/validation/"},{"categories":null,"content":"The result { } builder provides a fail-fast computation expression for standard F# Result values.\nBuilder FsFlow.Builders.result: The fail-fast result { } computation expression. ","description":"","linkTitle":"Result Builder","tags":null,"title":"Result Builder","uri":"/reference/result/"},{"categories":null,"content":"The Diagnostics type represents a structured graph of validation failures.\nGraph types FsFlow.PathSegment: Location markers used to describe where a diagnostic belongs in a validation graph. FsFlow.Path: A path through a validation graph, represented as a list of PathSegment. FsFlow.Diagnostic: A single failure item attached to a path in a validation graph. FsFlow.Diagnostics: A mergeable validation graph that carries local errors and nested child branches. Module functions FsFlow.DiagnosticsModule.empty: Creates an empty diagnostics graph with no errors. FsFlow.DiagnosticsModule.singleton: Creates a diagnostics graph containing exactly one error at the root. FsFlow.DiagnosticsModule.merge: Recursively merges two diagnostics graphs, combining shared branches and local errors. FsFlow.DiagnosticsModule.toString: Renders a diagnostics graph in a YAML-like layout for display. FsFlow.DiagnosticsModule.flatten: Flattens the structured diagnostics graph into a linear list of diagnostics. ","description":"","linkTitle":"Diagnostics","tags":null,"title":"Diagnostics","uri":"/reference/diagnostics/"},{"categories":null,"content":"This page shows the source-documented capability and layer surface, including CAPS request tokens and environment management helpers.\nCAPS tokens FsFlow.Needs: Describes the capability contract for a single dependency. FsFlow.Env: Request token for binding a whole dependency inside a workflow. FsFlow.Env: Request token for projecting a value from a dependency. Capabilities FsFlow.MissingCapability: Describes a missing service-provider capability. FsFlow.CapabilityModule.service: Reads a service from the environment using the provided projection. FsFlow.CapabilityModule.runtime: Reads the current runtime from the environment. FsFlow.CapabilityModule.environment: Reads the application environment from the environment. FsFlow.CapabilityModule.serviceFromProvider: Reads a service from IServiceProvider and fails when it is not registered. Layers FsFlow.LayerModule.provideLayer: Provides a derived environment from a layer flow to a downstream flow. ","description":"","linkTitle":"Capability","tags":null,"title":"Capability","uri":"/reference/capability/"},{"categories":null,"content":"FsFlow.Caps.Core is the smallest shared capability package in the FsFlow CAPS story. It keeps the surface synchronous and explicit: clock, random, GUID, and environment-variable capabilities.\nCapability types FsFlow.Caps.Core.IClock: Provides synchronous access to the current UTC clock. FsFlow.Caps.Core.IRandom: Provides synchronous random-number generation. FsFlow.Caps.Core.IGuid: Provides synchronous GUID generation. FsFlow.Caps.Core.IEnvironmentVariables: Provides synchronous environment-variable lookup. FsFlow.Caps.Core.EnvironmentVariableError: Describes a meaningful environment-variable failure. Clock FsFlow.Caps.Core.Clock.now: Reads the current UTC timestamp from the environment. FsFlow.Caps.Core.Clock.live: Creates a live clock backed by UtcNow. FsFlow.Caps.Core.Clock.fromValue: Creates a deterministic clock that always returns the supplied instant. Random FsFlow.Caps.Core.Random.nextInt: Reads a random integer from the environment. FsFlow.Caps.Core.Random.live: Creates a live random-number generator backed by Random. FsFlow.Caps.Core.Random.fromValue: Creates a deterministic random generator that always returns the supplied value. GUID FsFlow.Caps.Core.Guid.newGuid: Reads a GUID from the environment. FsFlow.Caps.Core.Guid.live: Creates a live GUID generator backed by NewGuid. FsFlow.Caps.Core.Guid.fromValue: Creates a deterministic GUID generator that always returns the supplied value. Environment variables FsFlow.Caps.Core.EnvironmentVariables.tryGet: Reads a raw environment-variable value from the environment. FsFlow.Caps.Core.EnvironmentVariables.live: Creates a live provider backed by the current process environment. FsFlow.Caps.Core.EnvironmentVariables.fromPairs: Creates a deterministic provider from a fixed set of name/value pairs. FsFlow.Caps.Core.EnvironmentVariable.tryGet: Reads a raw string environment variable without wrapping it in a result. FsFlow.Caps.Core.EnvironmentVariable.get: Reads a raw string environment variable from the environment. FsFlow.Caps.Core.EnvironmentVariable.getInt: Reads an integer environment variable from the environment. FsFlow.Caps.Core.EnvironmentVariable.getGuid: Reads a GUID environment variable from the environment. FsFlow.Caps.Core.EnvironmentVariable.getBool: Reads a boolean environment variable from the environment. FsFlow.Caps.Core.EnvironmentVariableErrors.describe: Formats a human-readable description for an error. ","description":"","linkTitle":"CAPS Core","tags":null,"title":"CAPS Core","uri":"/reference/caps-core/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Caps.Console surface: the console interface and its helpers.\nCapability FsFlow.Caps.Console.IConsole (undocumented) Helpers FsFlow.Caps.Console.Console.readLine (undocumented) FsFlow.Caps.Console.Console.writeLine (undocumented) FsFlow.Caps.Console.Console.live (undocumented) ","description":"","linkTitle":"CAPS Console","tags":null,"title":"CAPS Console","uri":"/reference/caps-console/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Caps.FileSystem surface: the file system interface and its helpers.\nCapability FsFlow.Caps.FileSystem.IFileSystem (undocumented) Helpers FsFlow.Caps.FileSystem.FileSystem.readAllText (undocumented) FsFlow.Caps.FileSystem.FileSystem.writeAllText (undocumented) FsFlow.Caps.FileSystem.FileSystem.exists (undocumented) FsFlow.Caps.FileSystem.FileSystem.live (undocumented) ","description":"","linkTitle":"CAPS FileSystem","tags":null,"title":"CAPS FileSystem","uri":"/reference/caps-filesystem/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Caps.Http surface: the HTTP interface and its helpers.\nCapability FsFlow.Caps.Http.IHttp (undocumented) Helpers FsFlow.Caps.Http.Http.getString (undocumented) FsFlow.Caps.Http.Http.live (undocumented) ","description":"","linkTitle":"CAPS Http","tags":null,"title":"CAPS Http","uri":"/reference/caps-http/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Caps.Process surface: the process runner interface and its helpers.\nCapability FsFlow.Caps.Process.IProcess (undocumented) FsFlow.Caps.Process.ProcessResult (undocumented) Helpers FsFlow.Caps.Process.Process.execute (undocumented) FsFlow.Caps.Process.Process.live (undocumented) ","description":"","linkTitle":"CAPS Process","tags":null,"title":"CAPS Process","uri":"/reference/caps-process/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Hosting surface: the IServiceProvider adapters and startup validation.\nStartup FsFlow.Hosting.Startup.validateEnvironment (undocumented) ","description":"","linkTitle":"Hosting","tags":null,"title":"Hosting","uri":"/reference/hosting/"},{"categories":null,"content":"This page shows the source-documented FsFlow.Runtime.Telemetry surface: Activity.trace integration.\nTracing FsFlow.Runtime.Telemetry.Activity.trace (undocumented) ","description":"","linkTitle":"Telemetry","tags":null,"title":"Telemetry","uri":"/reference/telemetry/"},{"categories":null,"content":"Returns success when every check in the sequence succeeds.\nRemarks Sequentially evaluates each check in the checks sequence. Stops at the first failure.\nParameters checks: A sequence of checks. Returns A Check that succeeds only if all inputs succeed.\n","description":"","linkTitle":"all`","tags":null,"title":"FsFlow.CheckModule.all","uri":"/reference/check/m-checkmodule-all/"},{"categories":null,"content":"Returns success when both checks succeed.\nRemarks This is a logical \u0026ldquo;and\u0026rdquo; operation. It short-circuits: if left fails, right is not evaluated.\nParameters left: The first check. right: The second check. Returns A Check that succeeds only if both inputs succeed.\n","description":"","linkTitle":"and`","tags":null,"title":"FsFlow.CheckModule.and","uri":"/reference/check/m-checkmodule-and/"},{"categories":null,"content":"Returns success when at least one check in the sequence succeeds.\nRemarks Sequentially evaluates each check in the checks sequence. Stops at the first success.\nParameters checks: A sequence of checks. Returns A Check that succeeds if any input succeeds.\n","description":"","linkTitle":"any`","tags":null,"title":"FsFlow.CheckModule.any","uri":"/reference/check/m-checkmodule-any/"},{"categories":null,"content":"Applies a flow-wrapped function to a flow-wrapped value.\n","description":"","linkTitle":"apply`","tags":null,"title":"FsFlow.Flow.apply","uri":"/reference/flow/m-flow-apply/"},{"categories":null,"content":"Applies a validation-wrapped function to a validation-wrapped value.\nParameters validation: The validation containing the function. value: The validation containing the value. Returns The result of applying the function to the value, with accumulated errors.\n","description":"","linkTitle":"apply`","tags":null,"title":"FsFlow.ValidationModule.apply","uri":"/reference/validation/m-validationmodule-apply/"},{"categories":null,"content":"Scopes a validation under the supplied path segments.\nParameters path: The path segments to apply to the validation. validation: The validation to scope. Returns A validation nested under the given path.\n","description":"","linkTitle":"at`","tags":null,"title":"FsFlow.ValidationModule.at","uri":"/reference/validation/m-validationmodule-at/"},{"categories":null,"content":"Executes an STM transaction atomically within a flow.\nParameters transaction: The STM transaction to execute. Returns A flow that performs the transaction and returns its result.\n","description":"","linkTitle":"atomically`","tags":null,"title":"FsFlow.STM.atomically","uri":"/reference/stm/m-stm-atomically/"},{"categories":null,"content":"Sequences a synchronous continuation after a successful value.\nRemarks This is the \u0026ldquo;flatmap\u0026rdquo; operation for Flow. It allows for dependent steps where the second flow depends on the value produced by the first.\nParameters binder: A function that takes the successful value and returns a new flow. flow: The source flow to sequence. Returns A Flow representing the combined workflow.\n","description":"","linkTitle":"bind`","tags":null,"title":"FsFlow.Flow.bind","uri":"/reference/flow/m-flow-bind/"},{"categories":null,"content":"Sequences a validation-producing continuation.\nRemarks This is the monadic \u0026ldquo;bind\u0026rdquo; for validation. Note that this operation short-circuits and does not accumulate errors from the binder if the source has already failed. For accumulation, use map2 or the applicative and! syntax.\nParameters binder: A function of type 'value -\u0026gt; Validation\u0026amp;lt;'next, 'error\u0026amp;gt;. validation: The source validation. Returns The result of the binder or the original diagnostics.\n","description":"","linkTitle":"bind`","tags":null,"title":"FsFlow.ValidationModule.bind","uri":"/reference/validation/m-validationmodule-bind/"},{"categories":null,"content":"Returns success when the string is blank.\nParameters str: The string to check. Returns A Check that succeeds if the string is blank.\n","description":"","linkTitle":"blank","tags":null,"title":"FsFlow.CheckModule.blank","uri":"/reference/check/m-checkmodule-blank/"},{"categories":null,"content":"Catches exceptions raised during execution and maps them to a typed error.\nRemarks Exceptions that are not caught by this helper will bubble up to the caller of run. This ensures that known exceptions can be handled within the flow context.\nParameters handler: A function of type exn -\u0026gt; 'error to map the exception. flow: The source flow of type Flow to monitor. Returns A Flow that converts exceptions into success-path errors.\n","description":"","linkTitle":"catch`","tags":null,"title":"FsFlow.Flow.catch","uri":"/reference/flow/m-flow-catch/"},{"categories":null,"content":"","description":"","linkTitle":"Categories","tags":null,"title":"Categories","uri":"/categories/"},{"categories":null,"content":"A reusable predicate result that either preserves a value on success or acts as a gate with unit on success, while carrying a unit failure placeholder until the caller maps it into a domain-specific error.\nRemarks Use the Check module helpers to create and compose checks.\n","description":"","linkTitle":"Check","tags":null,"title":"FsFlow.Check","uri":"/reference/check/t-check/"},{"categories":null,"content":"Collects a sequence of validations into a single validation of a list.\nRemarks This operation is applicative: it will collect errors from ALL items in the sequence.\nParameters validations: A sequence of type seq\u0026amp;lt;Validation\u0026amp;lt;'value, 'error\u0026amp;gt;\u0026amp;gt;. Returns A validation containing the list of values or accumulated diagnostics.\n","description":"","linkTitle":"collect`","tags":null,"title":"FsFlow.ValidationModule.collect","uri":"/reference/validation/m-validationmodule-collect/"},{"categories":null,"content":"Defers flow construction until execution time.\n","description":"","linkTitle":"delay`","tags":null,"title":"FsFlow.Flow.delay","uri":"/reference/flow/m-flow-delay/"},{"categories":null,"content":"Formats a human-readable description for an error.\n","description":"","linkTitle":"describe","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariableErrors.describe","uri":"/reference/caps-core/m-core-environmentvariableerrors-describe/"},{"categories":null,"content":"A single failure item attached to a path in a validation graph.\n","description":"","linkTitle":"Diagnostic","tags":null,"title":"FsFlow.Diagnostic","uri":"/reference/diagnostics/t-diagnostic/"},{"categories":null,"content":"A mergeable validation graph that carries local errors and nested child branches.\nRemarks `Errors` holds the application errors attached exactly to the current node, while `Children` holds nested branches keyed by `PathSegment`. This structure allows hierarchical validation to stay navigable before flattening. Use `flatten` to convert it into a linear list. ","description":"","linkTitle":"Diagnostics","tags":null,"title":"FsFlow.Diagnostics","uri":"/reference/diagnostics/t-diagnostics/"},{"categories":null,"content":"Creates an empty diagnostics graph with no errors.\nReturns An empty Diagnostics.\n","description":"","linkTitle":"empty`","tags":null,"title":"FsFlow.DiagnosticsModule.empty","uri":"/reference/diagnostics/m-diagnosticsmodule-empty/"},{"categories":null,"content":"Request token for projecting a value from a dependency.\nRemarks Builders read the dependency from the environment, apply the projection, and then reuse the existing lift/bind behavior for the projected value. If the projection returns a Result, Async, Task, ValueTask, ColdTask, option, or voption, the existing workflow rules still apply.\nExamples type IClock = abstract UtcNow : unit -\u0026amp;gt; DateTimeOffset type ClockCaps = inherit Needs\u0026amp;lt;IClock\u0026amp;gt; abstract Clock : IClock let readClockNow : Flow\u0026amp;lt;#ClockCaps, unit, DateTimeOffset\u0026amp;gt; = flow { let! now = Env\u0026amp;lt;IClock\u0026amp;gt; _.UtcNow return now } ","description":"","linkTitle":"Env","tags":null,"title":"FsFlow.Env","uri":"/reference/capability/t-env/"},{"categories":null,"content":"Reads the current environment as the flow value.\nRemarks Use this when the entire environment object is needed for the next step of the workflow. For projecting specific properties, read is generally more ergonomic.\nReturns A Flow whose successful value is the current environment.\n","description":"","linkTitle":"env`","tags":null,"title":"FsFlow.Flow.env","uri":"/reference/flow/m-flow-env/"},{"categories":null,"content":"Reads the application environment from the environment.\n","description":"","linkTitle":"environment`","tags":null,"title":"FsFlow.CapabilityModule.environment","uri":"/reference/capability/m-capabilitymodule-environment/"},{"categories":null,"content":"Describes a meaningful environment-variable failure.\n","description":"","linkTitle":"EnvironmentVariableError","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariableError","uri":"/reference/caps-core/t-core-environmentvariableerror/"},{"categories":null,"content":"Returns success when the values are equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values are equal.\n","description":"","linkTitle":"equal`","tags":null,"title":"FsFlow.CheckModule.equal","uri":"/reference/check/m-checkmodule-equal/"},{"categories":null,"content":"Creates a failing synchronous flow.\n","description":"","linkTitle":"error`","tags":null,"title":"FsFlow.Flow.error","uri":"/reference/flow/m-flow-error/"},{"categories":null,"content":"Creates a failing validation result with the provided diagnostics.\nParameters diagnostics: The Diagnostics graph. Returns A failing Validation.\n","description":"","linkTitle":"error`","tags":null,"title":"FsFlow.ValidationModule.error","uri":"/reference/validation/m-validationmodule-error/"},{"categories":null,"content":"Executes a process using the process environment and returns the result.\n","description":"","linkTitle":"execute`","tags":null,"title":"FsFlow.Caps.Process.ProcessModule.execute","uri":"/reference/caps-process/m-process-processmodule-execute/"},{"categories":null,"content":"Checks if a file exists using the file system environment.\n","description":"","linkTitle":"exists`","tags":null,"title":"FsFlow.Caps.FileSystem.FileSystemModule.exists","uri":"/reference/caps-filesystem/m-filesystem-filesystemmodule-exists/"},{"categories":null,"content":"Creates a schedule that recurs with exponential backoff.\n","description":"","linkTitle":"exponential`","tags":null,"title":"FsFlow.ScheduleModule.exponential","uri":"/reference/schedule/m-schedulemodule-exponential/"},{"categories":null,"content":"Alias for error that reads well in some call sites.\nExamples let flow = Flow.fail \u0026#34;error\u0026#34; let result = Flow.run () flow // result = Failure (Cause.Fail \u0026#34;error\u0026#34;) ","description":"","linkTitle":"fail`","tags":null,"title":"FsFlow.Flow.fail","uri":"/reference/flow/m-flow-fail/"},{"categories":null,"content":"Alias for error.\nParameters diagnostics: The Diagnostics graph. Returns A failing Validation.\n","description":"","linkTitle":"fail`","tags":null,"title":"FsFlow.ValidationModule.fail","uri":"/reference/validation/m-validationmodule-fail/"},{"categories":null,"content":"Returns success when the condition is false.\nParameters cond: The boolean condition to check. Returns A Check that succeeds if cond is false.\n","description":"","linkTitle":"failIf","tags":null,"title":"FsFlow.CheckModule.failIf","uri":"/reference/check/m-checkmodule-failif/"},{"categories":null,"content":"Returns the string when it is blank.\nParameters str: The string to check. Returns A Check containing the blank string.\n","description":"","linkTitle":"failIfBlank","tags":null,"title":"FsFlow.CheckModule.failIfBlank","uri":"/reference/check/m-checkmodule-failifblank/"},{"categories":null,"content":"Returns the sequence when it is not empty.\nParameters coll: The sequence to check. Returns A Check containing the non-empty sequence.\n","description":"","linkTitle":"failIfEmpty`","tags":null,"title":"FsFlow.CheckModule.failIfEmpty","uri":"/reference/check/m-checkmodule-failifempty/"},{"categories":null,"content":"Returns the string when it is null or empty.\nParameters str: The string to check. Returns A Check containing the empty or null string.\n","description":"","linkTitle":"failIfEmptyStr","tags":null,"title":"FsFlow.CheckModule.failIfEmptyStr","uri":"/reference/check/m-checkmodule-failifemptystr/"},{"categories":null,"content":"Returns success when the values are equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values are equal.\n","description":"","linkTitle":"failIfEqual`","tags":null,"title":"FsFlow.CheckModule.failIfEqual","uri":"/reference/check/m-checkmodule-failifequal/"},{"categories":null,"content":"Returns the value when the option is Some.\nParameters opt: The option to check. Returns A Check containing the value if present.\n","description":"","linkTitle":"failIfNone`","tags":null,"title":"FsFlow.CheckModule.failIfNone","uri":"/reference/check/m-checkmodule-failifnone/"},{"categories":null,"content":"Returns success when the string is null or empty.\nParameters str: The string to check. Returns A Check that succeeds if the string is null or empty.\n","description":"","linkTitle":"failIfNonEmptyStr","tags":null,"title":"FsFlow.CheckModule.failIfNonEmptyStr","uri":"/reference/check/m-checkmodule-failifnonemptystr/"},{"categories":null,"content":"Returns success when the string is blank.\nParameters str: The string to check. Returns A Check that succeeds if the string is blank.\n","description":"","linkTitle":"failIfNotBlank","tags":null,"title":"FsFlow.CheckModule.failIfNotBlank","uri":"/reference/check/m-checkmodule-failifnotblank/"},{"categories":null,"content":"Returns success when the sequence is empty.\nParameters coll: The sequence to check. Returns A Check that succeeds if the sequence is empty.\n","description":"","linkTitle":"failIfNotEmpty`","tags":null,"title":"FsFlow.CheckModule.failIfNotEmpty","uri":"/reference/check/m-checkmodule-failifnotempty/"},{"categories":null,"content":"Returns success when the values are not equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values differ.\n","description":"","linkTitle":"failIfNotEqual`","tags":null,"title":"FsFlow.CheckModule.failIfNotEqual","uri":"/reference/check/m-checkmodule-failifnotequal/"},{"categories":null,"content":"Returns success when the value is null.\nParameters value: The value to check. Returns A Check that succeeds if the value is null.\n","description":"","linkTitle":"failIfNotNull`","tags":null,"title":"FsFlow.CheckModule.failIfNotNull","uri":"/reference/check/m-checkmodule-failifnotnull/"},{"categories":null,"content":"Returns the value when it is null.\nParameters value: The value to check. Returns A Check containing the null value.\n","description":"","linkTitle":"failIfNull`","tags":null,"title":"FsFlow.CheckModule.failIfNull","uri":"/reference/check/m-checkmodule-failifnull/"},{"categories":null,"content":"Returns success when the option is None.\nParameters opt: The option to check. Returns A Check that succeeds if the option is None.\n","description":"","linkTitle":"failIfSome`","tags":null,"title":"FsFlow.CheckModule.failIfSome","uri":"/reference/check/m-checkmodule-failifsome/"},{"categories":null,"content":"Returns the value when the value option is ValueSome.\nParameters opt: The value option to check. Returns A Check containing the value if present.\n","description":"","linkTitle":"failIfValueNone`","tags":null,"title":"FsFlow.CheckModule.failIfValueNone","uri":"/reference/check/m-checkmodule-failifvaluenone/"},{"categories":null,"content":"Returns success when the value option is ValueNone.\nParameters opt: The value option to check. Returns A Check that succeeds if the value option is ValueNone.\n","description":"","linkTitle":"failIfValueSome`","tags":null,"title":"FsFlow.CheckModule.failIfValueSome","uri":"/reference/check/m-checkmodule-failifvaluesome/"},{"categories":null,"content":"Represents a handle to a running workflow.\n","description":"","linkTitle":"Fiber","tags":null,"title":"FsFlow.Fiber","uri":"/reference/flow/t-fiber/"},{"categories":null,"content":"Flattens the structured diagnostics graph into a linear list of diagnostics.\nRemarks During flattening, child paths are accumulated from the root down into each emitted diagnostic. The tree itself stores only local errors and child branches, while Diagnostic is reserved for reporting output.\nParameters graph: The Diagnostics to flatten. Returns A list of type Diagnostic list.\n","description":"","linkTitle":"flatten`","tags":null,"title":"FsFlow.DiagnosticsModule.flatten","uri":"/reference/diagnostics/m-diagnosticsmodule-flatten/"},{"categories":null,"content":"The universal flow { } computation expression.\nRemarks Use this builder when the boundary can mix synchronous values, `Async`, `Task`, `Result`, and environment requests while keeping typed failures and explicit dependency access. It preserves the current environment model while allowing the workflow to compose task-oriented inputs directly, so callers do not need to switch builders just to cross an async boundary. Examples let greeting = flow { let! name = Flow.env let! suffix = async { return \u0026#34;!\u0026#34; } return $\u0026#34;Hello, {name}{suffix}\u0026#34; } ","description":"","linkTitle":"flow","tags":null,"title":"FsFlow.Builders.flow","uri":"/reference/flow/p-builders-flow/"},{"categories":null,"content":"Represents a cold workflow that reads an environment, returns a typed result, and is executed explicitly through Flow.run.\n","description":"","linkTitle":"Flow","tags":null,"title":"FsFlow.Flow","uri":"/reference/flow/t-flow/"},{"categories":null,"content":"The flow { } builder is the primary entry point for orchestrating synchronous, async, and task-based work.\nBuilder FsFlow.Builders.flow: The universal flow { } computation expression. ","description":"","linkTitle":"flow { }","tags":null,"title":"flow { }","uri":"/reference/flow/builders-flow/"},{"categories":null,"content":"Represents a cold stream of values that requires an environment, can fail with a typed error, and supports backpressure.\n","description":"","linkTitle":"FlowStream","tags":null,"title":"FsFlow.FlowStream","uri":"/reference/stream/t-flowstream/"},{"categories":null,"content":"Starts a flow in a new fiber without waiting for it to complete.\nParameters flow: The flow to fork. Returns A flow that produces a Fiber handle.\n","description":"","linkTitle":"fork`","tags":null,"title":"FsFlow.Flow.fork","uri":"/reference/flow/m-flow-fork/"},{"categories":null,"content":"Lifts an option into a synchronous flow with the supplied error.\nExamples let opt = Some \u0026#34;value\u0026#34; let flow = Flow.fromOption \u0026#34;missing\u0026#34; opt ","description":"","linkTitle":"fromOption`","tags":null,"title":"FsFlow.Flow.fromOption","uri":"/reference/flow/m-flow-fromoption/"},{"categories":null,"content":"Creates a deterministic provider from a fixed set of name/value pairs.\n","description":"","linkTitle":"fromPairs","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariables.fromPairs","uri":"/reference/caps-core/m-core-environmentvariables-frompairs/"},{"categories":null,"content":"Builds a check from a predicate while preserving the successful value.\nParameters predicate: A function of type 'value -\u0026gt; bool to test the value. value: The value of type 'value to check. Returns A Check containing the value if the predicate succeeds.\n","description":"","linkTitle":"fromPredicate`","tags":null,"title":"FsFlow.CheckModule.fromPredicate","uri":"/reference/check/m-checkmodule-frompredicate/"},{"categories":null,"content":"Lifts a Result into a synchronous flow.\nExamples let res = Ok \u0026#34;success\u0026#34; let flow = Flow.fromResult res ","description":"","linkTitle":"fromResult`","tags":null,"title":"FsFlow.Flow.fromResult","uri":"/reference/flow/m-flow-fromresult/"},{"categories":null,"content":"Lifts a standard Result into the Validation context.\nRemarks If the result is an error, it is wrapped in a root-level Diagnostics graph.\nParameters result: The result to lift. Returns A Validation mirroring the result.\n","description":"","linkTitle":"fromResult`","tags":null,"title":"FsFlow.ValidationModule.fromResult","uri":"/reference/validation/m-validationmodule-fromresult/"},{"categories":null,"content":"Creates a stream from a sequence of values.\n","description":"","linkTitle":"fromSeq`","tags":null,"title":"FsFlow.FlowStreamModule.fromSeq","uri":"/reference/stream/m-flowstreammodule-fromseq/"},{"categories":null,"content":"Creates a deterministic clock that always returns the supplied instant.\n","description":"","linkTitle":"fromValue","tags":null,"title":"FsFlow.Caps.Core.Clock.fromValue","uri":"/reference/caps-core/m-core-clock-fromvalue/"},{"categories":null,"content":"Creates a deterministic GUID generator that always returns the supplied value.\n","description":"","linkTitle":"fromValue","tags":null,"title":"FsFlow.Caps.Core.Guid.fromValue","uri":"/reference/caps-core/m-core-guid-fromvalue/"},{"categories":null,"content":"Creates a deterministic random generator that always returns the supplied value.\n","description":"","linkTitle":"fromValue","tags":null,"title":"FsFlow.Caps.Core.Random.fromValue","uri":"/reference/caps-core/m-core-random-fromvalue/"},{"categories":null,"content":"Lifts a value option into a synchronous flow with the supplied error.\nParameters error: The error to return if the value option is ValueNone. value: The value option to lift. Returns A Flow that succeeds with the option\u0026rsquo;s value or fails with the provided error.\n","description":"","linkTitle":"fromValueOption`","tags":null,"title":"FsFlow.Flow.fromValueOption","uri":"/reference/flow/m-flow-fromvalueoption/"},{"categories":null,"content":"Reads a raw string environment variable from the environment.\n","description":"","linkTitle":"get`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariable.get","uri":"/reference/caps-core/m-core-environmentvariable-get/"},{"categories":null,"content":"Reads the current value of the reference.\n","description":"","linkTitle":"get`","tags":null,"title":"FsFlow.RefModule.get","uri":"/reference/ref/m-refmodule-get/"},{"categories":null,"content":"Reads the current value of the transactional reference within a transaction.\n","description":"","linkTitle":"get`","tags":null,"title":"FsFlow.TRefModule.get","uri":"/reference/stm/m-trefmodule-get/"},{"categories":null,"content":"Reads a boolean environment variable from the environment.\n","description":"","linkTitle":"getBool`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariable.getBool","uri":"/reference/caps-core/m-core-environmentvariable-getbool/"},{"categories":null,"content":"Reads a GUID environment variable from the environment.\n","description":"","linkTitle":"getGuid`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariable.getGuid","uri":"/reference/caps-core/m-core-environmentvariable-getguid/"},{"categories":null,"content":"Reads an integer environment variable from the environment.\n","description":"","linkTitle":"getInt`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariable.getInt","uri":"/reference/caps-core/m-core-environmentvariable-getint/"},{"categories":null,"content":"Sends a GET request using the HTTP environment and returns the response body.\n","description":"","linkTitle":"getString`","tags":null,"title":"FsFlow.Caps.Http.HttpModule.getString","uri":"/reference/caps-http/m-http-httpmodule-getstring/"},{"categories":null,"content":" One model from predicate checks to task execution A single model for Result-based programs in F#. Write predicate checks once. Keep fail-fast logic in Result, accumulate multiple failures with Validation, then lift the same logic into Flow when the boundary needs environment access, async work, task interop, cancellation, or runtime policy. Pure Checks -\u003e Result \u0026 Validation Flow Typed failure Explicit environment Runtime context Cold execution semantics Get Started \u0026gt; Check once, lift later type RegistrationError = | EmailMissing | UserNotFound let validateEmail (email: string) : Result\u0026lt;string, RegistrationError\u0026gt; = email |\u0026gt; Check.notBlank |\u0026gt; Check.orError EmailMissing type User = { Email: string } type Api = { LoadUser: int -\u0026gt; Task\u0026lt;Result\u0026lt;User, RegistrationError\u0026gt;\u0026gt; } type Clock = { UtcNow: DateTimeOffset } let readVerifiedEmail userId = flow { let! user = Env\u0026lt;Api\u0026gt; (_.LoadUser userId) let! checkedAt = Env\u0026lt;Clock\u0026gt; _.UtcNow let! email = validateEmail user.Email return email, checkedAt } Examples \u0026gt; ","description":"FsFlow technical guides, semantics, and API reference.","linkTitle":"Home","tags":null,"title":"Home","uri":"/"},{"categories":null,"content":"Provides synchronous access to the current UTC clock.\n","description":"","linkTitle":"IClock","tags":null,"title":"FsFlow.Caps.Core.IClock","uri":"/reference/caps-core/t-core-iclock/"},{"categories":null,"content":"Provides synchronous access to standard console I/O.\n","description":"","linkTitle":"IConsole","tags":null,"title":"FsFlow.Caps.Console.IConsole","uri":"/reference/caps-console/t-console-iconsole/"},{"categories":null,"content":"Provides synchronous environment-variable lookup.\n","description":"","linkTitle":"IEnvironmentVariables","tags":null,"title":"FsFlow.Caps.Core.IEnvironmentVariables","uri":"/reference/caps-core/t-core-ienvironmentvariables/"},{"categories":null,"content":"Provides synchronous access to file system operations.\n","description":"","linkTitle":"IFileSystem","tags":null,"title":"FsFlow.Caps.FileSystem.IFileSystem","uri":"/reference/caps-filesystem/t-filesystem-ifilesystem/"},{"categories":null,"content":"Maps the successful value of a synchronous flow to unit.\n","description":"","linkTitle":"ignore`","tags":null,"title":"FsFlow.Flow.ignore","uri":"/reference/flow/m-flow-ignore/"},{"categories":null,"content":"Maps a successful validation value to unit while preserving the diagnostics.\nParameters validation: The source validation. Returns A validation that keeps the original diagnostics and discards the success value.\n","description":"","linkTitle":"ignore`","tags":null,"title":"FsFlow.ValidationModule.ignore","uri":"/reference/validation/m-validationmodule-ignore/"},{"categories":null,"content":"Provides synchronous GUID generation.\n","description":"","linkTitle":"IGuid","tags":null,"title":"FsFlow.Caps.Core.IGuid","uri":"/reference/caps-core/t-core-iguid/"},{"categories":null,"content":"Provides asynchronous access to HTTP client operations.\n","description":"","linkTitle":"IHttp","tags":null,"title":"FsFlow.Caps.Http.IHttp","uri":"/reference/caps-http/t-http-ihttp/"},{"categories":null,"content":"Prefixes a validation with an indexed branch.\nParameters index: The branch index. validation: The validation to scope. Returns A validation whose diagnostics are prefixed with Index index.\n","description":"","linkTitle":"index`","tags":null,"title":"FsFlow.ValidationModule.index","uri":"/reference/validation/m-validationmodule-index/"},{"categories":null,"content":"Signals a fiber to stop and waits for it to finish its cleanup.\nParameters fiber: The fiber to interrupt. Returns A flow that completes with the fiber\u0026rsquo;s final outcome after interruption.\n","description":"","linkTitle":"interrupt`","tags":null,"title":"FsFlow.Flow.interrupt","uri":"/reference/flow/m-flow-interrupt/"},{"categories":null,"content":"Provides asynchronous access to external process execution.\n","description":"","linkTitle":"IProcess","tags":null,"title":"FsFlow.Caps.Process.IProcess","uri":"/reference/caps-process/t-process-iprocess/"},{"categories":null,"content":"Provides synchronous random-number generation.\n","description":"","linkTitle":"IRandom","tags":null,"title":"FsFlow.Caps.Core.IRandom","uri":"/reference/caps-core/t-core-irandom/"},{"categories":null,"content":"Adds random jitter to a schedule\u0026rsquo;s delay.\n","description":"","linkTitle":"jittered`","tags":null,"title":"FsFlow.ScheduleModule.jittered","uri":"/reference/schedule/m-schedulemodule-jittered/"},{"categories":null,"content":"Waits for a fiber to complete and returns its final outcome.\nParameters fiber: The fiber to join. Returns A flow that completes with the fiber\u0026rsquo;s outcome.\n","description":"","linkTitle":"join`","tags":null,"title":"FsFlow.Flow.join","uri":"/reference/flow/m-flow-join/"},{"categories":null,"content":"Prefixes a validation with a keyed branch.\nParameters key: The branch key. validation: The validation to scope. Returns A validation whose diagnostics are prefixed with Key key.\n","description":"","linkTitle":"key`","tags":null,"title":"FsFlow.ValidationModule.key","uri":"/reference/validation/m-validationmodule-key/"},{"categories":null,"content":"Creates a live console backed by Console.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Console.ConsoleModule.live","uri":"/reference/caps-console/p-console-consolemodule-live/"},{"categories":null,"content":"Creates a live clock backed by UtcNow.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Core.Clock.live","uri":"/reference/caps-core/p-core-clock-live/"},{"categories":null,"content":"Creates a live provider backed by the current process environment.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariables.live","uri":"/reference/caps-core/p-core-environmentvariables-live/"},{"categories":null,"content":"Creates a live GUID generator backed by NewGuid.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Core.Guid.live","uri":"/reference/caps-core/p-core-guid-live/"},{"categories":null,"content":"Creates a live random-number generator backed by Random.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Core.Random.live","uri":"/reference/caps-core/p-core-random-live/"},{"categories":null,"content":"Creates a live file system backed by File.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.FileSystem.FileSystemModule.live","uri":"/reference/caps-filesystem/p-filesystem-filesystemmodule-live/"},{"categories":null,"content":"Creates a live HTTP client backed by HttpClient.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Http.HttpModule.live","uri":"/reference/caps-http/m-http-httpmodule-live/"},{"categories":null,"content":"Creates a live process runner backed by Process.\n","description":"","linkTitle":"live","tags":null,"title":"FsFlow.Caps.Process.ProcessModule.live","uri":"/reference/caps-process/p-process-processmodule-live/"},{"categories":null,"content":"Transforms the environment before running the flow.\n","description":"","linkTitle":"localEnv`","tags":null,"title":"FsFlow.Flow.localEnv","uri":"/reference/flow/m-flow-localenv/"},{"categories":null,"content":"Creates a new Ref with the initial value.\n","description":"","linkTitle":"make`","tags":null,"title":"FsFlow.RefModule.make","uri":"/reference/ref/m-refmodule-make/"},{"categories":null,"content":"Creates a new TRef with the initial value.\n","description":"","linkTitle":"make`","tags":null,"title":"FsFlow.TRefModule.make","uri":"/reference/stm/m-trefmodule-make/"},{"categories":null,"content":"Maps the successful value of a synchronous flow.\nRemarks If the source flow fails, the mapper is not executed, and the error is preserved. This allows for safe transformation of data within the flow.\nParameters mapper: A function of type 'value -\u0026gt; 'next to transform the successful value. flow: The source flow of type Flow to transform. Returns A new Flow with the transformed success value of type 'next.\n","description":"","linkTitle":"map`","tags":null,"title":"FsFlow.Flow.map","uri":"/reference/flow/m-flow-map/"},{"categories":null,"content":"Maps the successful values of a stream.\n","description":"","linkTitle":"map`","tags":null,"title":"FsFlow.FlowStreamModule.map","uri":"/reference/stream/m-flowstreammodule-map/"},{"categories":null,"content":"Maps the successful value of a validation.\nParameters mapper: A function of type 'value -\u0026gt; 'next. validation: The source Validation. Returns A validation with the transformed success value.\n","description":"","linkTitle":"map`","tags":null,"title":"FsFlow.ValidationModule.map","uri":"/reference/validation/m-validationmodule-map/"},{"categories":null,"content":"Combines two flows with a mapping function.\n","description":"","linkTitle":"map2`","tags":null,"title":"FsFlow.Flow.map2","uri":"/reference/flow/m-flow-map2/"},{"categories":null,"content":"Combines two validations, accumulating errors if both fail.\nRemarks This is the core applicative operation. If both left and right fail, their diagnostics graphs are merged.\nParameters mapper: A function of type 'left -\u0026gt; 'right -\u0026gt; 'value. left: The first validation. right: The second validation. Returns A validation with the combined result.\n","description":"","linkTitle":"map2`","tags":null,"title":"FsFlow.ValidationModule.map2","uri":"/reference/validation/m-validationmodule-map2/"},{"categories":null,"content":"Combines three flows with a mapping function.\n","description":"","linkTitle":"map3`","tags":null,"title":"FsFlow.Flow.map3","uri":"/reference/flow/m-flow-map3/"},{"categories":null,"content":"Combines three validations, accumulating errors when any input fails.\nParameters mapper: A function of type 'left -\u0026gt; 'middle -\u0026gt; 'right -\u0026gt; 'value. left: The first validation. middle: The second validation. right: The third validation. Returns A validation with the combined result.\n","description":"","linkTitle":"map3`","tags":null,"title":"FsFlow.ValidationModule.map3","uri":"/reference/validation/m-validationmodule-map3/"},{"categories":null,"content":"Maps the error value of a synchronous flow.\nRemarks Transforms the error type of the flow while leaving successful values untouched. Useful for mapping internal errors into public-facing domain errors.\nParameters mapper: The function to transform the error value. flow: The source flow. Returns A Flow with the transformed error type.\n","description":"","linkTitle":"mapError`","tags":null,"title":"FsFlow.Flow.mapError","uri":"/reference/flow/m-flow-maperror/"},{"categories":null,"content":"Maps the error type of a validation graph.\nParameters mapper: A function of type 'error -\u0026gt; 'nextError. validation: The source Validation. Returns A validation with transformed error values.\n","description":"","linkTitle":"mapError`","tags":null,"title":"FsFlow.ValidationModule.mapError","uri":"/reference/validation/m-validationmodule-maperror/"},{"categories":null,"content":"Recursively merges two diagnostics graphs, combining shared branches and local errors.\nRemarks This is the core operation for applicative validation. It ensures that errors from sibling fields are collected together into a single structured graph.\nParameters left: The first graph of type Diagnostics. right: The second graph of type Diagnostics. Returns A new Diagnostics containing the union of both inputs.\n","description":"","linkTitle":"merge`","tags":null,"title":"FsFlow.DiagnosticsModule.merge","uri":"/reference/diagnostics/m-diagnosticsmodule-merge/"},{"categories":null,"content":"Merges two validations into a validation of a tuple.\nParameters left: The first validation. right: The second validation. Returns A validation containing a tuple of the results.\n","description":"","linkTitle":"merge`","tags":null,"title":"FsFlow.ValidationModule.merge","uri":"/reference/validation/m-validationmodule-merge/"},{"categories":null,"content":"Describes a missing service-provider capability.\n","description":"","linkTitle":"MissingCapability","tags":null,"title":"FsFlow.MissingCapability","uri":"/reference/capability/t-missingcapability/"},{"categories":null,"content":"Updates the value of the reference using the supplied function and returns a derived value.\n","description":"","linkTitle":"modify`","tags":null,"title":"FsFlow.RefModule.modify","uri":"/reference/ref/m-refmodule-modify/"},{"categories":null,"content":"Prefixes a validation with a named branch.\nParameters name: The branch name. validation: The validation to scope. Returns A validation whose diagnostics are prefixed with Name name.\n","description":"","linkTitle":"name`","tags":null,"title":"FsFlow.ValidationModule.name","uri":"/reference/validation/m-validationmodule-name/"},{"categories":null,"content":"Describes the capability contract for a single dependency.\nRemarks Named cap-set interfaces inherit this contract once and then expose the dependency through a member such as Clock or Logger. Workflow builders can accept any environment that implements Needs\u0026amp;lt;'dep\u0026amp;gt;, which lets larger runtimes satisfy smaller boundaries.\nExamples type IClock = abstract UtcNow : unit -\u0026amp;gt; DateTimeOffset type ClockCaps = inherit Needs\u0026amp;lt;IClock\u0026amp;gt; abstract Clock : IClock ","description":"","linkTitle":"Needs","tags":null,"title":"FsFlow.Needs","uri":"/reference/capability/t-needs/"},{"categories":null,"content":"Reads a GUID from the environment.\n","description":"","linkTitle":"newGuid`","tags":null,"title":"FsFlow.Caps.Core.Guid.newGuid","uri":"/reference/caps-core/m-core-guid-newguid/"},{"categories":null,"content":"Reads a random integer from the environment.\n","description":"","linkTitle":"nextInt`","tags":null,"title":"FsFlow.Caps.Core.Random.nextInt","uri":"/reference/caps-core/m-core-random-nextint/"},{"categories":null,"content":"Returns success when the supplied check fails.\nRemarks This is a logical \u0026ldquo;not\u0026rdquo; operation for checks. Note that it discards the success value and returns Unit on success.\nParameters check: The source Check to invert. Returns A Check that succeeds if the input fails.\n","description":"","linkTitle":"not`","tags":null,"title":"FsFlow.CheckModule.not","uri":"/reference/check/m-checkmodule-not/"},{"categories":null,"content":"Returns the string when it is not blank.\nParameters str: The string to check. Returns A Check containing the non-blank string.\n","description":"","linkTitle":"notBlank","tags":null,"title":"FsFlow.CheckModule.notBlank","uri":"/reference/check/m-checkmodule-notblank/"},{"categories":null,"content":"Returns the sequence when it is not empty.\nParameters coll: The sequence to check. Returns A Check containing the non-empty sequence.\n","description":"","linkTitle":"notEmpty`","tags":null,"title":"FsFlow.CheckModule.notEmpty","uri":"/reference/check/m-checkmodule-notempty/"},{"categories":null,"content":"Returns success when the values are not equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values differ.\n","description":"","linkTitle":"notEqual`","tags":null,"title":"FsFlow.CheckModule.notEqual","uri":"/reference/check/m-checkmodule-notequal/"},{"categories":null,"content":"Returns the value when it is not null.\nParameters value: The value to check. Returns A Check containing the non-null value.\n","description":"","linkTitle":"notNull`","tags":null,"title":"FsFlow.CheckModule.notNull","uri":"/reference/check/m-checkmodule-notnull/"},{"categories":null,"content":"Reads the current UTC timestamp from the environment.\n","description":"","linkTitle":"now`","tags":null,"title":"FsFlow.Caps.Core.Clock.now","uri":"/reference/caps-core/m-core-clock-now/"},{"categories":null,"content":"Creates a successful synchronous flow.\n","description":"","linkTitle":"ok`","tags":null,"title":"FsFlow.Flow.ok","uri":"/reference/flow/m-flow-ok/"},{"categories":null,"content":"Creates a successful validation result.\nParameters value: The success value of type 'value. Returns A successful Validation.\n","description":"","linkTitle":"ok`","tags":null,"title":"FsFlow.ValidationModule.ok","uri":"/reference/validation/m-validationmodule-ok/"},{"categories":null,"content":"Returns success when the condition is true.\nParameters cond: The boolean condition to check. Returns A Check that succeeds if cond is true.\n","description":"","linkTitle":"okIf","tags":null,"title":"FsFlow.CheckModule.okIf","uri":"/reference/check/m-checkmodule-okif/"},{"categories":null,"content":"Returns success when the string is blank.\nParameters str: The string to check. Returns A Check that succeeds if the string is null, empty, or whitespace.\n","description":"","linkTitle":"okIfBlank","tags":null,"title":"FsFlow.CheckModule.okIfBlank","uri":"/reference/check/m-checkmodule-okifblank/"},{"categories":null,"content":"Returns success when the sequence is empty.\nParameters coll: The sequence to check. Returns A Check that succeeds if the sequence is empty.\n","description":"","linkTitle":"okIfEmpty`","tags":null,"title":"FsFlow.CheckModule.okIfEmpty","uri":"/reference/check/m-checkmodule-okifempty/"},{"categories":null,"content":"Returns success when the string is null or empty.\nParameters str: The string to check. Returns A Check that succeeds if the string is null or empty.\n","description":"","linkTitle":"okIfEmptyStr","tags":null,"title":"FsFlow.CheckModule.okIfEmptyStr","uri":"/reference/check/m-checkmodule-okifemptystr/"},{"categories":null,"content":"Returns success when the values are equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values are equal.\n","description":"","linkTitle":"okIfEqual`","tags":null,"title":"FsFlow.CheckModule.okIfEqual","uri":"/reference/check/m-checkmodule-okifequal/"},{"categories":null,"content":"Returns success when the option is None.\nParameters opt: The option to check. Returns A Check that succeeds if the option is None.\n","description":"","linkTitle":"okIfNone`","tags":null,"title":"FsFlow.CheckModule.okIfNone","uri":"/reference/check/m-checkmodule-okifnone/"},{"categories":null,"content":"Returns the string when it is not null or empty.\nParameters str: The string to check. Returns A Check containing the non-empty string.\n","description":"","linkTitle":"okIfNonEmptyStr","tags":null,"title":"FsFlow.CheckModule.okIfNonEmptyStr","uri":"/reference/check/m-checkmodule-okifnonemptystr/"},{"categories":null,"content":"Returns the string when it is not blank.\nParameters str: The string to check. Returns A Check containing the non-blank string.\n","description":"","linkTitle":"okIfNotBlank","tags":null,"title":"FsFlow.CheckModule.okIfNotBlank","uri":"/reference/check/m-checkmodule-okifnotblank/"},{"categories":null,"content":"Returns the sequence when it is not empty.\nParameters coll: The sequence of type seq\u0026amp;lt;'a\u0026amp;gt; to check. Returns A Check containing the non-empty sequence.\n","description":"","linkTitle":"okIfNotEmpty`","tags":null,"title":"FsFlow.CheckModule.okIfNotEmpty","uri":"/reference/check/m-checkmodule-okifnotempty/"},{"categories":null,"content":"Returns success when the values are not equal.\nParameters expected: The expected value. actual: The actual value. Returns A Check that succeeds if the values differ.\n","description":"","linkTitle":"okIfNotEqual`","tags":null,"title":"FsFlow.CheckModule.okIfNotEqual","uri":"/reference/check/m-checkmodule-okifnotequal/"},{"categories":null,"content":"Returns the value when it is not null.\nParameters value: The value of type 'a to check for null. Returns A Check containing the non-null value.\n","description":"","linkTitle":"okIfNotNull`","tags":null,"title":"FsFlow.CheckModule.okIfNotNull","uri":"/reference/check/m-checkmodule-okifnotnull/"},{"categories":null,"content":"Returns success when the value is null.\nParameters value: The value to check. Returns A Check that succeeds if the value is null.\n","description":"","linkTitle":"okIfNull`","tags":null,"title":"FsFlow.CheckModule.okIfNull","uri":"/reference/check/m-checkmodule-okifnull/"},{"categories":null,"content":"Returns the value when the option is Some.\nParameters opt: The FSharpOption to check. Returns A Check containing the value if present.\n","description":"","linkTitle":"okIfSome`","tags":null,"title":"FsFlow.CheckModule.okIfSome","uri":"/reference/check/m-checkmodule-okifsome/"},{"categories":null,"content":"Returns success when the value option is ValueNone.\nParameters opt: The value option to check. Returns A Check that succeeds if the value option is ValueNone.\n","description":"","linkTitle":"okIfValueNone`","tags":null,"title":"FsFlow.CheckModule.okIfValueNone","uri":"/reference/check/m-checkmodule-okifvaluenone/"},{"categories":null,"content":"Returns the value when the value option is ValueSome.\nParameters opt: The FSharpValueOption to check. Returns A Check containing the value if present.\n","description":"","linkTitle":"okIfValueSome`","tags":null,"title":"FsFlow.CheckModule.okIfValueSome","uri":"/reference/check/m-checkmodule-okifvaluesome/"},{"categories":null,"content":"Returns success when either check succeeds.\nRemarks This is a logical \u0026ldquo;or\u0026rdquo; operation. It short-circuits: if left succeeds, right is not evaluated.\nParameters left: The first check. right: The second check. Returns A Check that succeeds if either input succeeds.\n","description":"","linkTitle":"or`","tags":null,"title":"FsFlow.CheckModule.or","uri":"/reference/check/m-checkmodule-or/"},{"categories":null,"content":"Falls back to another flow when the source flow fails.\n","description":"","linkTitle":"orElse`","tags":null,"title":"FsFlow.Flow.orElse","uri":"/reference/flow/m-flow-orelse/"},{"categories":null,"content":"Falls back to another validation when the source validation fails.\nRemarks This is a left-biased choice operator. If the source succeeds, the fallback is not used. If the source fails, the fallback validation is returned as-is.\nParameters fallback: The validation to use when the source fails. validation: The source validation. Returns The source validation when it succeeds, otherwise the fallback validation.\n","description":"","linkTitle":"orElse`","tags":null,"title":"FsFlow.ValidationModule.orElse","uri":"/reference/validation/m-validationmodule-orelse/"},{"categories":null,"content":"Turns a pure validation result into a synchronous flow with environment-provided failure.\nRemarks This helper bridges the gap between pure validation (which often uses Result or Check) and the Flow environment model. If the result is an error, the provided errorFlow is executed to produce the final application error.\nParameters errorFlow: A flow that reads the environment to produce an error value. result: The pure result to bridge. Returns A Flow that mirrors the success of the result or fails with the outcome of the error flow.\n","description":"","linkTitle":"orElseFlow`","tags":null,"title":"FsFlow.Flow.orElseFlow","uri":"/reference/flow/m-flow-orelseflow/"},{"categories":null,"content":"Falls back to another flow when the source flow fails.\n","description":"","linkTitle":"orElseWith`","tags":null,"title":"FsFlow.Flow.orElseWith","uri":"/reference/flow/m-flow-orelsewith/"},{"categories":null,"content":"Computes a fallback validation from the source diagnostics when validation fails.\nRemarks This is the lazy counterpart to orElse and is useful when the alternate branch depends on the accumulated diagnostics.\nParameters fallback: A function that turns the diagnostics into an alternate validation. validation: The source validation. Returns The source validation when it succeeds, otherwise the computed fallback validation.\n","description":"","linkTitle":"orElseWith`","tags":null,"title":"FsFlow.ValidationModule.orElseWith","uri":"/reference/validation/m-validationmodule-orelsewith/"},{"categories":null,"content":"Maps a unit error into the supplied application error value.\nRemarks This is the primary bridge from checks to domain-specific results.\nParameters error: The domain error of type 'error to return on failure. result: The source Check. Returns A Result with the provided error value.\n","description":"","linkTitle":"orError`","tags":null,"title":"FsFlow.CheckModule.orError","uri":"/reference/check/m-checkmodule-orerror/"},{"categories":null,"content":"Maps a unit error into an application error produced on demand.\nParameters errorFn: A function of type unit -\u0026gt; 'error to produce the error. result: The source Check. Returns A Result with the produced error value.\n","description":"","linkTitle":"orErrorWith`","tags":null,"title":"FsFlow.CheckModule.orErrorWith","uri":"/reference/check/m-checkmodule-orerrorwith/"},{"categories":null,"content":"A path through a validation graph, represented as a list of PathSegment.\n","description":"","linkTitle":"Path","tags":null,"title":"FsFlow.Path","uri":"/reference/diagnostics/t-path/"},{"categories":null,"content":"Location markers used to describe where a diagnostic belongs in a validation graph.\n","description":"","linkTitle":"PathSegment","tags":null,"title":"FsFlow.PathSegment","uri":"/reference/diagnostics/t-pathsegment/"},{"categories":null,"content":"Represents the outcome of an external process execution.\n","description":"","linkTitle":"ProcessResult","tags":null,"title":"FsFlow.Caps.Process.ProcessResult","uri":"/reference/caps-process/t-process-processresult/"},{"categories":null,"content":"Provides a derived environment from a layer flow to a downstream flow.\n","description":"","linkTitle":"provideLayer`","tags":null,"title":"FsFlow.LayerModule.provideLayer","uri":"/reference/capability/m-layermodule-providelayer/"},{"categories":null,"content":"Provides a derived environment from a layer flow to a downstream flow.\n","description":"","linkTitle":"provideLayer`","tags":null,"title":"FsFlow.Flow.provideLayer","uri":"/reference/flow/m-flow-providelayer/"},{"categories":null,"content":"Runs two flows concurrently and returns the result of the first one to complete.\nRemarks The \u0026ldquo;loser\u0026rdquo; flow is interrupted immediately.\n","description":"","linkTitle":"race`","tags":null,"title":"FsFlow.Flow.race","uri":"/reference/flow/m-flow-race/"},{"categories":null,"content":"Projects a value from the current environment.\nRemarks This is the primary way to access dependencies or configuration stored in the environment. The projection function is applied to the environment at execution time.\nParameters projection: A function that extracts a value from the environment. Returns A Flow containing the projected value.\n","description":"","linkTitle":"read`","tags":null,"title":"FsFlow.Flow.read","uri":"/reference/flow/m-flow-read/"},{"categories":null,"content":"Reads all text from a file using the file system environment.\n","description":"","linkTitle":"readAllText`","tags":null,"title":"FsFlow.Caps.FileSystem.FileSystemModule.readAllText","uri":"/reference/caps-filesystem/m-filesystem-filesystemmodule-readalltext/"},{"categories":null,"content":"Reads a line from the console environment.\n","description":"","linkTitle":"readLine`","tags":null,"title":"FsFlow.Caps.Console.ConsoleModule.readLine","uri":"/reference/caps-console/m-console-consolemodule-readline/"},{"categories":null,"content":"Creates a schedule that recurs a fixed number of times.\n","description":"","linkTitle":"recurs`","tags":null,"title":"FsFlow.ScheduleModule.recurs","uri":"/reference/schedule/m-schedulemodule-recurs/"},{"categories":null,"content":"The Ref module provides thread-safe mutable state handles.\nCore type FsFlow.Ref: Represents a handle to a mutable reference that can be updated atomically. Module functions FsFlow.RefModule.make: Creates a new Ref with the initial value. FsFlow.RefModule.get: Reads the current value of the reference. FsFlow.RefModule.set: Sets the value of the reference to the specified value. FsFlow.RefModule.update: Updates the value of the reference using the supplied function. FsFlow.RefModule.modify: Updates the value of the reference using the supplied function and returns a derived value. ","description":"","linkTitle":"Ref","tags":null,"title":"Ref","uri":"/reference/ref/"},{"categories":null,"content":"Represents a handle to a mutable reference that can be updated atomically.\n","description":"","linkTitle":"Ref","tags":null,"title":"FsFlow.Ref","uri":"/reference/ref/t-ref/"},{"categories":null,"content":"The fail-fast result { } computation expression.\nRemarks Use this builder when the happy path should short-circuit on the first error and you want to keep the workflow in `Result` shape all the way through. It works well for parsing, validation, and other boundaries where failure is expected to stop the flow immediately instead of accumulating diagnostics. Use `Check.orError` when a pure check needs a domain error, and `Guard.MapError` when you need to remap an existing error before entering the CE. Examples let parsedUser = result { let! age = parseAge input let! name = parseName input return { Age = age; Name = name } } ","description":"","linkTitle":"result","tags":null,"title":"FsFlow.Builders.result","uri":"/reference/result/p-builders-result/"},{"categories":null,"content":"The result { } builder provides a fail-fast computation expression for standard F# Result values.\nBuilder FsFlow.Builders.result: The fail-fast result { } computation expression. ","description":"","linkTitle":"Result Builder","tags":null,"title":"Result Builder","uri":"/reference/result/builders-result/"},{"categories":null,"content":"Executes a flow with the provided environment and the default cancellation token.\nExamples let flow = Flow.read (fun env -\u0026gt; $\u0026#34;Hello, {env}!\u0026#34;) let result = Flow.run \u0026#34;World\u0026#34; flow // result = Effect that resolves to Success \u0026#34;Hello, World!\u0026#34; on both .NET and Fable ","description":"","linkTitle":"run`","tags":null,"title":"FsFlow.Flow.run","uri":"/reference/flow/m-flow-run/"},{"categories":null,"content":"Executes the stream and performs an action for each value.\n","description":"","linkTitle":"runForEach`","tags":null,"title":"FsFlow.FlowStreamModule.runForEach","uri":"/reference/stream/m-flowstreammodule-runforeach/"},{"categories":null,"content":"Runnable Examples This page shows the examples that are executed during the docs build, so the public docs stay tied to real code and observed output.\nThe examples below are built from the repository projects, run with the current source, and then written back into this page.\nThe code blocks keep the important API calls on the same lines as the values they bind, with trailing comments where that makes the signature easier to read. The examples prefer the normal direct-bind style inside computation expressions, so the docs reflect the recommended day-to-day usage.\nRequest Boundary Example This example shows a request boundary that pulls a user from a database-like environment, threads a trace id through the request context, and reuses the same validation shape across Flow.\nRun it:\nFSFLOW_EXAMPLE=request-boundary dotnet run --project examples/FsFlow.Examples/FsFlow.Examples.fsproj --nologo Source:\nRequestBoundaryExample.fs Source code:\nmodule RequestBoundaryExample open System open System.Threading open System.Threading.Tasks open FsFlow type User = { Id: int Name: string } type AppDb = { FindUser: int -\u0026gt; User option } type RequestEnv = { TraceId: Guid Prefix: string Db: AppDb LoadSuffix: Task\u0026lt;string\u0026gt; } let validateName (name: string) : Result\u0026lt;string, string\u0026gt; = Check.notBlank name |\u0026gt; Check.orError \u0026#34;name is required\u0026#34; let loadUser : Flow\u0026lt;RequestEnv, string, User\u0026gt; = flow { let! db = Flow.read _.Db // Flow\u0026lt;RequestEnv, string, AppDb\u0026gt; let! user = db.FindUser 42 |\u0026gt; Flow.fromOption \u0026#34;user not found\u0026#34; // Flow\u0026lt;RequestEnv, string, User\u0026gt; return user } let renderTrace : Flow\u0026lt;RequestEnv, string, string\u0026gt; = flow { let! env = Flow.env // Flow\u0026lt;RequestEnv, string, RequestEnv\u0026gt; let! user = loadUser // Flow\u0026lt;RequestEnv, string, User\u0026gt; let! validName = validateName user.Name // Flow\u0026lt;RequestEnv, string, string\u0026gt; return $\u0026#34;{env.Prefix} [{env.TraceId}] {validName}\u0026#34; } let publishResponse : Flow\u0026lt;RequestEnv, string, string\u0026gt; = flow { let! env = Flow.env // Flow\u0026lt;RequestEnv, string, RequestEnv\u0026gt; let! user = loadUser // Flow\u0026lt;RequestEnv, string, User\u0026gt; let! suffix = env.LoadSuffix // Flow\u0026lt;RequestEnv, string, string\u0026gt; return $\u0026#34;{env.Prefix} [{env.TraceId}] {user.Name}{suffix}\u0026#34; } let run () = let environment = { TraceId = Guid.Parse \u0026#34;11111111-1111-1111-1111-111111111111\u0026#34; Prefix = \u0026#34;Hello\u0026#34; Db = { FindUser = function | 42 -\u0026gt; Some { Id = 42; Name = \u0026#34;Ada\u0026#34; } | _ -\u0026gt; None } LoadSuffix = Task.FromResult \u0026#34;!\u0026#34; } let syncResult = loadUser |\u0026gt; Flow.run environment |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() let asyncResult = renderTrace |\u0026gt; Flow.run environment |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() let taskResult = publishResponse |\u0026gt; Flow.run environment |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;Flow result: %A\u0026#34; syncResult printfn \u0026#34;Flow result: %A\u0026#34; asyncResult printfn \u0026#34;Flow result: %A\u0026#34; taskResult // Flow result: Ok { Id = 42; Name = \u0026#34;Ada\u0026#34; } // Flow result: Ok \u0026#34;Hello [11111111-1111-1111-1111-111111111111] Ada\u0026#34; // Flow result: Ok \u0026#34;Hello [11111111-1111-1111-1111-111111111111] Ada!\u0026#34; Diagnostics Example This example shows a JSON-shaped request boundary with a root-level error, nested child branches, and a display-friendly diagnostics tree.\nRun it:\nFSFLOW_EXAMPLE=diagnostics dotnet run --project examples/FsFlow.Examples/FsFlow.Examples.fsproj --nologo Source:\nDiagnosticsExample.fs Source code:\nmodule DiagnosticsExample open System.Text.Json open FsFlow type CustomerLine = { Name: string } type CustomerAddress = { City: string } type Customer = { Name: string Address: CustomerAddress Lines: CustomerLine list } type CreateCustomerRequest = { RequestId: string Customer: Customer } type ApiError = { path: string message: string } type ApiErrorResponse = { errors: ApiError list } let jsonOptions = JsonSerializerOptions(WriteIndented = true) let validateAddress address = validate.key \u0026#34;address\u0026#34; { let! city = validate.name \u0026#34;City\u0026#34; { return! address.City |\u0026gt; Check.notBlank |\u0026gt; Check.orError \u0026#34;City required\u0026#34; } return { address with City = city } } let validateCustomer customer = validate { let! name = validate.name \u0026#34;Name\u0026#34; { return! customer.Name |\u0026gt; Check.notBlank |\u0026gt; Check.orError \u0026#34;Name required\u0026#34; } and! address = validateAddress customer.Address and! lines = validate.key \u0026#34;lines\u0026#34; { return! customer.Lines |\u0026gt; Validation.traverseIndexed (fun index line -\u0026gt; validate.name \u0026#34;Name\u0026#34; { let! name = line.Name |\u0026gt; Check.notBlank |\u0026gt; Check.orError $\u0026#34;Line {index} name required\u0026#34; return { Name = name } } ) } return { customer with Name = name Address = address Lines = lines } } let renderPath (path: PathSegment list) = path |\u0026gt; List.map (function | PathSegment.Key value | PathSegment.Name value -\u0026gt; value | PathSegment.Index index -\u0026gt; $\u0026#34;[{index}]\u0026#34;) |\u0026gt; String.concat \u0026#34;.\u0026#34; let toApiErrors (graph: Diagnostics\u0026lt;\u0026#39;error\u0026gt;) = { errors = graph |\u0026gt; Diagnostics.flatten |\u0026gt; List.map (fun diagnostic -\u0026gt; { path = renderPath diagnostic.Path message = string diagnostic.Error }) } let validateCreateCustomerRequest request = validate { let! requestId = validate.name \u0026#34;RequestId\u0026#34; { return! request.RequestId |\u0026gt; Check.notBlank |\u0026gt; Check.orError \u0026#34;RequestId required\u0026#34; } and! customer = validate.key \u0026#34;customer\u0026#34; { return! validateCustomer request.Customer } return { request with RequestId = requestId; Customer = customer } } let run () = let requestJson = \u0026#34;\u0026#34;\u0026#34;{ \u0026#34;requestId\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;customer\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;address\u0026#34;: { \u0026#34;city\u0026#34;: \u0026#34;\u0026#34; }, \u0026#34;lines\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;\u0026#34; } ] } }\u0026#34;\u0026#34;\u0026#34; let badRequest = { RequestId = \u0026#34;\u0026#34; Customer = { Name = \u0026#34;\u0026#34; Address = { City = \u0026#34;\u0026#34; } Lines = [ { Name = \u0026#34;\u0026#34; } ] } } let diagnosticsText = validateCreateCustomerRequest badRequest |\u0026gt; Validation.toResult |\u0026gt; Result.mapError (toApiErrors \u0026gt;\u0026gt; fun payload -\u0026gt; JsonSerializer.Serialize(payload, jsonOptions)) |\u0026gt; function | Ok _ -\u0026gt; \u0026#34;Ok\u0026#34; | Error text -\u0026gt; text printfn \u0026#34;Request JSON:\\n%s\u0026#34; requestJson printfn \u0026#34;API error JSON:\\n%s\u0026#34; diagnosticsText // Request JSON: // { // \u0026#34;requestId\u0026#34;: \u0026#34;\u0026#34;, // \u0026#34;customer\u0026#34;: { // \u0026#34;name\u0026#34;: \u0026#34;\u0026#34;, // \u0026#34;address\u0026#34;: { \u0026#34;city\u0026#34;: \u0026#34;\u0026#34; }, // \u0026#34;lines\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;\u0026#34; } ] // } // } // API error JSON: // { // \u0026#34;errors\u0026#34;: [ // { // \u0026#34;path\u0026#34;: \u0026#34;customer.address.City\u0026#34;, // \u0026#34;message\u0026#34;: \u0026#34;City required\u0026#34; // }, // { // \u0026#34;path\u0026#34;: \u0026#34;customer.lines.[0].Name\u0026#34;, // \u0026#34;message\u0026#34;: \u0026#34;Line 0 name required\u0026#34; // }, // { // \u0026#34;path\u0026#34;: \u0026#34;customer.Name\u0026#34;, // \u0026#34;message\u0026#34;: \u0026#34;Name required\u0026#34; // }, // { // \u0026#34;path\u0026#34;: \u0026#34;RequestId\u0026#34;, // \u0026#34;message\u0026#34;: \u0026#34;RequestId required\u0026#34; // } // ] // } CAPS Core Example This example shows the sync-first FsFlow.Caps.Core surface: fixed and live capability providers, plus typed errors for missing and invalid environment variables.\nRun it:\ndotnet run --project examples/FsFlow.Caps.Core.Examples/FsFlow.Caps.Core.Examples.fsproj --nologo Source:\nCoreCapabilitiesExample.fs Source code:\nnamespace FsFlow.Caps.Core.Examples open System open FsFlow open FsFlow.Caps.Core module CoreCapabilitiesExample = type private AppCaps = { Clock: IClock Random: IRandom Guid: IGuid EnvVars: IEnvironmentVariables } interface Needs\u0026lt;IClock\u0026gt; with member this.Dep = this.Clock interface Needs\u0026lt;IRandom\u0026gt; with member this.Dep = this.Random interface Needs\u0026lt;IGuid\u0026gt; with member this.Dep = this.Guid interface Needs\u0026lt;IEnvironmentVariables\u0026gt; with member this.Dep = this.EnvVars let private renderExit formatter result = match result with | Exit.Success value -\u0026gt; $\u0026#34;Ok {formatter value}\u0026#34; | Exit.Failure (Cause.Fail error) -\u0026gt; $\u0026#34;Error {EnvironmentVariableErrors.describe error}\u0026#34; | Exit.Failure cause -\u0026gt; $\u0026#34;Failure {cause}\u0026#34; let run () = let caps = { Clock = Clock.fromValue (DateTimeOffset(2026, 5, 10, 12, 0, 0, TimeSpan.Zero)) Random = Random.fromValue 7 Guid = Guid.fromValue (global.System.Guid.Parse \u0026#34;11111111-1111-1111-1111-111111111111\u0026#34;) EnvVars = EnvironmentVariables.fromPairs [ \u0026#34;FSFLOW_CAPS_PORT\u0026#34;, \u0026#34;8080\u0026#34; \u0026#34;FSFLOW_CAPS_ENABLED\u0026#34;, \u0026#34;true\u0026#34; \u0026#34;FSFLOW_CAPS_SESSION\u0026#34;, \u0026#34;22222222-2222-2222-2222-222222222222\u0026#34; \u0026#34;FSFLOW_CAPS_PORT_TEXT\u0026#34;, \u0026#34;abc\u0026#34; ] } let run flow = Flow.run caps flow |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;clock=%O\u0026#34; (run Clock.now) printfn \u0026#34;random=%d\u0026#34; (run (Random.nextInt 0 10) |\u0026gt; function Exit.Success v -\u0026gt; v | _ -\u0026gt; -1) printfn \u0026#34;guid=%O\u0026#34; (run Guid.newGuid) printfn \u0026#34;port=%s\u0026#34; (renderExit string (run (EnvironmentVariable.getInt \u0026#34;FSFLOW_CAPS_PORT\u0026#34;))) printfn \u0026#34;enabled=%s\u0026#34; (renderExit string (run (EnvironmentVariable.getBool \u0026#34;FSFLOW_CAPS_ENABLED\u0026#34;))) printfn \u0026#34;session=%s\u0026#34; (renderExit string (run (EnvironmentVariable.getGuid \u0026#34;FSFLOW_CAPS_SESSION\u0026#34;))) printfn \u0026#34;missing=%s\u0026#34; (renderExit string (run (EnvironmentVariable.get \u0026#34;FSFLOW_CAPS_MISSING\u0026#34;))) printfn \u0026#34;invalid=%s\u0026#34; (renderExit string (run (EnvironmentVariable.getInt \u0026#34;FSFLOW_CAPS_PORT_TEXT\u0026#34;))) Playground Example This example shows the same core boundary across Flow using the normal direct-bind style inside each computation expression.\nRun it:\ndotnet run --project examples/FsFlow.Playground/FsFlow.Playground.fsproj --nologo Source:\nProgram.fs Source code:\nopen System open System.Threading open System.Threading.Tasks open FsFlow type AppEnv = { Prefix: string Name: string LoadSuffix: Task\u0026lt;string\u0026gt; } let greetingFlow : Flow\u0026lt;AppEnv, string, string\u0026gt; = Flow.read (fun env -\u0026gt; $\u0026#34;{env.Prefix} {env.Name}\u0026#34;) // Flow\u0026lt;AppEnv, string, string\u0026gt; let greetingAsync : Flow\u0026lt;AppEnv, string, string\u0026gt; = flow { let! greeting = greetingFlow return greeting.ToUpperInvariant() } let greetingTask : Flow\u0026lt;AppEnv, string, string\u0026gt; = flow { let! env = Flow.env // Flow\u0026lt;AppEnv, string, AppEnv\u0026gt; let! greeting = greetingFlow // Flow\u0026lt;AppEnv, string, string\u0026gt; let! suffix = env.LoadSuffix // Flow\u0026lt;AppEnv, string, string\u0026gt; return $\u0026#34;{greeting}{suffix}\u0026#34; } [\u0026lt;EntryPoint\u0026gt;] let main _ = let env = { Prefix = \u0026#34;Hello\u0026#34; Name = \u0026#34;Ada\u0026#34; LoadSuffix = Task.FromResult \u0026#34;!\u0026#34; } let syncResult = greetingFlow |\u0026gt; Flow.run env |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() let asyncResult = greetingAsync |\u0026gt; Flow.run env |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() let taskResult = greetingTask |\u0026gt; Flow.run env |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;Flow: %A\u0026#34; syncResult printfn \u0026#34;Async: %A\u0026#34; asyncResult printfn \u0026#34;Task: %A\u0026#34; taskResult // Flow: Ok \u0026#34;Hello Ada\u0026#34; // Async: Ok \u0026#34;HELLO ADA\u0026#34; // Task: Ok \u0026#34;Hello Ada!\u0026#34; 0 Maintenance Example This example shows smaller, focused shapes for maintenance and interop scenarios without switching away from the normal direct-bind style.\nRun it:\ndotnet run --project examples/FsFlow.MaintenanceExamples/FsFlow.MaintenanceExamples.fsproj --nologo Source:\nProgram.fs Source code:\nopen System open System.Threading open System.Threading.Tasks open FsFlow let runFlow label env workflow = let result = Flow.run env workflow |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;%s: %A\u0026#34; label result let runAsyncExample label env workflow = let result = workflow |\u0026gt; Flow.run env |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;%s: %A\u0026#34; label result let runTaskExample label env workflow = let result = workflow |\u0026gt; Flow.run env |\u0026gt; fun t -\u0026gt; t.AsTask().GetAwaiter().GetResult() printfn \u0026#34;%s: %A\u0026#34; label result let syncExample : Flow\u0026lt;int, string, int\u0026gt; = Flow.read id // Flow\u0026lt;int, string, int\u0026gt; |\u0026gt; Flow.map ((+) 1) let asyncExample : Flow\u0026lt;int, string, int\u0026gt; = flow { let! value = async { return 21 } return value * 2 } let taskExample : Flow\u0026lt;int, string, int\u0026gt; = flow { let! env = Flow.read id let! suffix = Task.FromResult 5 return env + suffix } [\u0026lt;EntryPoint\u0026gt;] let main _ = runFlow \u0026#34;Flow\u0026#34; 20 syncExample runAsyncExample \u0026#34;Async\u0026#34; 20 asyncExample runTaskExample \u0026#34;Task\u0026#34; 20 taskExample // Flow: Ok 21 // Async: Ok 42 // Task: Ok 25 0 ","description":"Application-shaped examples that are executed during docs generation and mirrored back into the site.","linkTitle":"Runnable Examples","tags":null,"title":"Runnable Examples","uri":"/docs/patterns/examples/"},{"categories":null,"content":"Reads the current runtime from the environment.\n","description":"","linkTitle":"runtime`","tags":null,"title":"FsFlow.CapabilityModule.runtime","uri":"/reference/capability/m-capabilitymodule-runtime/"},{"categories":null,"content":"The Schedule module provides a DSL for describing execution policies.\nCore type FsFlow.Schedule: Represents a stateful schedule that can decide whether to continue and how long to delay. Module functions FsFlow.ScheduleModule.recurs: Creates a schedule that recurs a fixed number of times. FsFlow.ScheduleModule.spaced: Creates a schedule that recurs with a fixed delay between attempts. FsFlow.ScheduleModule.exponential: Creates a schedule that recurs with exponential backoff. FsFlow.ScheduleModule.jittered: Adds random jitter to a schedule\u0026rsquo;s delay. Flow extensions FsFlow.FlowScheduleExtensions.Flow.Retry.Static: Retries a failing flow according to the supplied schedule. FsFlow.FlowScheduleExtensions.Flow.Repeat.Static: Repeats a successful flow according to the supplied schedule. ","description":"","linkTitle":"Schedule","tags":null,"title":"Schedule","uri":"/reference/schedule/"},{"categories":null,"content":"Represents a stateful schedule that can decide whether to continue and how long to delay.\n","description":"","linkTitle":"Schedule","tags":null,"title":"FsFlow.Schedule","uri":"/reference/schedule/t-schedule/"},{"categories":null,"content":"Transforms a sequence of flows into a flow of a sequence and stops at the first failure.\n","description":"","linkTitle":"sequence`","tags":null,"title":"FsFlow.Flow.sequence","uri":"/reference/flow/m-flow-sequence/"},{"categories":null,"content":"Transforms a sequence of validations into a validation of a list.\nParameters validations: The input sequence. Returns A validation containing the list of values.\n","description":"","linkTitle":"sequence`","tags":null,"title":"FsFlow.ValidationModule.sequence","uri":"/reference/validation/m-validationmodule-sequence/"},{"categories":null,"content":"Reads a service from the environment using the provided projection.\n","description":"","linkTitle":"service`","tags":null,"title":"FsFlow.CapabilityModule.service","uri":"/reference/capability/m-capabilitymodule-service/"},{"categories":null,"content":"Reads a service from IServiceProvider and fails when it is not registered.\n","description":"","linkTitle":"serviceFromProvider`","tags":null,"title":"FsFlow.CapabilityModule.serviceFromProvider","uri":"/reference/capability/m-capabilitymodule-servicefromprovider/"},{"categories":null,"content":"Sets the value of the reference to the specified value.\n","description":"","linkTitle":"set`","tags":null,"title":"FsFlow.RefModule.set","uri":"/reference/ref/m-refmodule-set/"},{"categories":null,"content":"Sets the value of the transactional reference within a transaction.\n","description":"","linkTitle":"set`","tags":null,"title":"FsFlow.TRefModule.set","uri":"/reference/stm/m-trefmodule-set/"},{"categories":null,"content":"Creates a diagnostics graph containing exactly one error at the root.\nParameters error: The application error to store at the root. Returns A Diagnostics with a single error.\n","description":"","linkTitle":"singleton`","tags":null,"title":"FsFlow.DiagnosticsModule.singleton","uri":"/reference/diagnostics/m-diagnosticsmodule-singleton/"},{"categories":null,"content":"Creates a schedule that recurs with a fixed delay between attempts.\n","description":"","linkTitle":"spaced`","tags":null,"title":"FsFlow.ScheduleModule.spaced","uri":"/reference/schedule/m-schedulemodule-spaced/"},{"categories":null,"content":"Repeats a successful flow according to the supplied schedule.\n","description":"","linkTitle":"Static`","tags":null,"title":"FsFlow.FlowScheduleExtensions.Flow.Repeat.Static","uri":"/reference/schedule/m-flowscheduleextensions-flow-repeat-static/"},{"categories":null,"content":"Retries a failing flow according to the supplied schedule.\n","description":"","linkTitle":"Static`","tags":null,"title":"FsFlow.FlowScheduleExtensions.Flow.Retry.Static","uri":"/reference/schedule/m-flowscheduleextensions-flow-retry-static/"},{"categories":null,"content":"The stm { } computation expression for building atomic transactions.\n","description":"","linkTitle":"stm","tags":null,"title":"FsFlow.StmBuilders.stm","uri":"/reference/stm/p-stmbuilders-stm/"},{"categories":null,"content":"The STM module provides composable atomic transactions.\nCore types FsFlow.TRef: Represents a transactional reference that can be updated atomically within an STM transaction. FsFlow.STM: Represents a transactional operation that can be composed and executed atomically. Module functions FsFlow.TRefModule.make: Creates a new TRef with the initial value. FsFlow.TRefModule.get: Reads the current value of the transactional reference within a transaction. FsFlow.TRefModule.set: Sets the value of the transactional reference within a transaction. FsFlow.TRefModule.update: Updates the value of the transactional reference within a transaction using the supplied function. FsFlow.STM.atomically: Executes an STM transaction atomically within a flow. Builder FsFlow.StmBuilders.stm: The stm { } computation expression for building atomic transactions. ","description":"","linkTitle":"STM","tags":null,"title":"STM","uri":"/reference/stm/"},{"categories":null,"content":"Represents a transactional operation that can be composed and executed atomically.\n","description":"","linkTitle":"STM","tags":null,"title":"FsFlow.STM","uri":"/reference/stm/t-stm/"},{"categories":null,"content":"The FlowStream module provides asynchronous, pull-based streams.\nCore type FsFlow.FlowStream: Represents a cold stream of values that requires an environment, can fail with a typed error, and supports backpressure. Module functions FsFlow.FlowStreamModule.fromSeq: Creates a stream from a sequence of values. FsFlow.FlowStreamModule.map: Maps the successful values of a stream. FsFlow.FlowStreamModule.runForEach: Executes the stream and performs an action for each value. ","description":"","linkTitle":"Stream","tags":null,"title":"Stream","uri":"/reference/stream/"},{"categories":null,"content":"Alias for ok that reads well in some call sites.\nExamples let flow = Flow.succeed 42 let result = Flow.run () flow // result = Success 42 ","description":"","linkTitle":"succeed`","tags":null,"title":"FsFlow.Flow.succeed","uri":"/reference/flow/m-flow-succeed/"},{"categories":null,"content":"Alias for ok.\nParameters value: The success value of type 'value. Returns A successful Validation.\n","description":"","linkTitle":"succeed`","tags":null,"title":"FsFlow.ValidationModule.succeed","uri":"/reference/validation/m-validationmodule-succeed/"},{"categories":null,"content":"","description":"","linkTitle":"Tags","tags":null,"title":"Tags","uri":"/tags/"},{"categories":null,"content":"Runs a synchronous side effect on success and preserves the original value.\nRemarks Use this for logging, telemetry, or other \u0026ldquo;fire and forget\u0026rdquo; operations that should not alter the primary value path. If the binder flow fails, the entire flow fails with that error.\nParameters binder: A function that produces a side-effect flow from the successful value. flow: The source flow. Returns A Flow that preserves the original success value after the side effect.\n","description":"","linkTitle":"tap`","tags":null,"title":"FsFlow.Flow.tap","uri":"/reference/flow/m-flow-tap/"},{"categories":null,"content":"Runs a synchronous side effect on failure and preserves the original error.\nRemarks Use this for error logging or cleanup actions that depend on the environment. If the binder side-effect flow itself fails, its error will overwrite the original error.\nParameters binder: A function that produces a side-effect flow from the error value. flow: The source flow. Returns A Flow that preserves the original error after the side effect.\n","description":"","linkTitle":"tapError`","tags":null,"title":"FsFlow.Flow.tapError","uri":"/reference/flow/m-flow-taperror/"},{"categories":null,"content":"Converts a Validation into a standard Result.\nParameters validation: The validation to convert. Returns A result containing either the success value or the full diagnostics graph.\n","description":"","linkTitle":"toResult`","tags":null,"title":"FsFlow.ValidationModule.toResult","uri":"/reference/validation/m-validationmodule-toresult/"},{"categories":null,"content":"Renders a diagnostics graph in a YAML-like layout for display.\nRemarks This is intended for human-readable output. Empty sections are omitted, and children are shown directly under their branch labels at the same indentation level as errors. Errors render as YAML-style bullet items without an Errors: key. Use flatten when you need path-bearing diagnostics for reporting or assertions.\nParameters graph: The diagnostics graph to render. Returns A formatted string representation of the graph.\n","description":"","linkTitle":"toString`","tags":null,"title":"FsFlow.DiagnosticsModule.toString","uri":"/reference/diagnostics/m-diagnosticsmodule-tostring/"},{"categories":null,"content":"Wraps a flow in a new activity and automatically maps metadata traits from the environment to tags.\nParameters name: The name of the activity. flow: The flow to trace. Returns A flow that executes within the activity span.\n","description":"","linkTitle":"trace`","tags":null,"title":"FsFlow.Runtime.Telemetry.Activity.trace","uri":"/reference/telemetry/m-runtime-telemetry-activity-trace/"},{"categories":null,"content":"Transforms a sequence of values into a flow and stops at the first failure.\n","description":"","linkTitle":"traverse`","tags":null,"title":"FsFlow.Flow.traverse","uri":"/reference/flow/m-flow-traverse/"},{"categories":null,"content":"Maps a sequence into validations while prefixing each item with its index.\nRemarks This is the indexed version of sequence. It is useful for list and array validation because each item can keep its own Index branch without the caller manually wrapping every item.\nParameters binder: A function of type int -\u0026gt; 'source -\u0026gt; Validation\u0026amp;lt;'value, 'error\u0026amp;gt;. values: The input sequence. Returns A validation containing the list of values or accumulated diagnostics.\n","description":"","linkTitle":"traverseIndexed`","tags":null,"title":"FsFlow.ValidationModule.traverseIndexed","uri":"/reference/validation/m-validationmodule-traverseindexed/"},{"categories":null,"content":"Represents a transactional reference that can be updated atomically within an STM transaction.\n","description":"","linkTitle":"TRef","tags":null,"title":"FsFlow.TRef","uri":"/reference/stm/t-tref/"},{"categories":null,"content":"Reads a raw string environment variable without wrapping it in a result.\n","description":"","linkTitle":"tryGet`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariable.tryGet","uri":"/reference/caps-core/m-core-environmentvariable-tryget/"},{"categories":null,"content":"Reads a raw environment-variable value from the environment.\n","description":"","linkTitle":"tryGet`","tags":null,"title":"FsFlow.Caps.Core.EnvironmentVariables.tryGet","uri":"/reference/caps-core/m-core-environmentvariables-tryget/"},{"categories":null,"content":"Updates the value of the reference using the supplied function.\n","description":"","linkTitle":"update`","tags":null,"title":"FsFlow.RefModule.update","uri":"/reference/ref/m-refmodule-update/"},{"categories":null,"content":"Updates the value of the transactional reference within a transaction using the supplied function.\n","description":"","linkTitle":"update`","tags":null,"title":"FsFlow.TRefModule.update","uri":"/reference/stm/m-trefmodule-update/"},{"categories":null,"content":"The accumulating validate { } computation expression.\nRemarks Use this builder when you want to collect all validation failures instead of stopping at the first one. Use `and!` when sibling validations should accumulate into the same diagnostics graph. Plain `let!` and `do!` are sequential: if the left side fails, the later step is not evaluated. `Check\u003c'value\u003e` covers both value-preserving checks and gate checks. Use `Check.orError` to attach an application error, and `Guard.Of` / `Guard.MapError` when you want the same error-bound source shape to participate directly in validation. When nested API response fields need to keep their place in the diagnostics graph, use the scoped helpers `validate.key`, `validate.index`, and `validate.name` inside the computation expression. If you already have a `Validation` value, use `Validation.key`, `Validation.index`, or `Validation.name` to prefix it after the fact. It is intended for forms, configuration checks, and other input-heavy boundaries where the user benefits from seeing every problem at once. Examples let validatedUser = validate { let! name = Check.notBlank input.Name let! age = Check.okIf (input.Age \u0026gt; 0) \u0026#34;Age must be positive\u0026#34; return { Name = name; Age = age } } let validatedCustomer = validate.key \u0026#34;customer\u0026#34; { let! name = validate.name \u0026#34;Name\u0026#34; { return! input.Name |\u0026gt; Check.notBlank |\u0026gt; Check.orError \u0026#34;Name required\u0026#34; } return name } ","description":"","linkTitle":"validate","tags":null,"title":"FsFlow.Builders.validate","uri":"/reference/validation/p-builders-validate/"},{"categories":null,"content":"The validate { } builder is used for accumulating sibling failures into a structured diagnostics graph.\nBuilder FsFlow.Builders.validate: The accumulating validate { } computation expression. ","description":"","linkTitle":"validate { }","tags":null,"title":"validate { }","uri":"/reference/validation/builders-validate/"},{"categories":null,"content":"Validates that all required environment variables are present and valid using the process environment.\n","description":"","linkTitle":"validateEnvironment`","tags":null,"title":"FsFlow.Hosting.Startup.validateEnvironment","uri":"/reference/hosting/m-hosting-startup-validateenvironment/"},{"categories":null,"content":"An accumulating validation result that keeps the structured diagnostics graph visible.\nRemarks Unlike FSharpResult, this type is designed for applicative composition using and! in the validate { } builder, which merges errors instead of short-circuiting.\n","description":"","linkTitle":"Validation","tags":null,"title":"FsFlow.Validation","uri":"/reference/validation/t-validation/"},{"categories":null,"content":"Alias for ok that reads well in some call sites.\nExamples let flow = Flow.value \u0026#34;constant\u0026#34; ","description":"","linkTitle":"value`","tags":null,"title":"FsFlow.Flow.value","uri":"/reference/flow/m-flow-value/"},{"categories":null,"content":"Writes all text to a file using the file system environment.\n","description":"","linkTitle":"writeAllText`","tags":null,"title":"FsFlow.Caps.FileSystem.FileSystemModule.writeAllText","uri":"/reference/caps-filesystem/m-filesystem-filesystemmodule-writealltext/"},{"categories":null,"content":"Writes a line to the console environment.\n","description":"","linkTitle":"writeLine`","tags":null,"title":"FsFlow.Caps.Console.ConsoleModule.writeLine","uri":"/reference/caps-console/m-console-consolemodule-writeline/"},{"categories":null,"content":"Combines two flows into a tuple of their values.\n","description":"","linkTitle":"zip`","tags":null,"title":"FsFlow.Flow.zip","uri":"/reference/flow/m-flow-zip/"},{"categories":null,"content":"Combines two flows into a tuple of their values, running them concurrently.\nRemarks If either flow fails, the other is interrupted immediately.\n","description":"","linkTitle":"zipPar`","tags":null,"title":"FsFlow.Flow.zipPar","uri":"/reference/flow/m-flow-zippar/"}]