Repository F# setup
open Reified
open Reified.Refinements
open Reified.Result

Result handling

Maturity: Incubating

Reified.Result works with the standard F# Result<'value, 'error>. Other F# code can pattern match its Ok and Error values.

Its module and DSL convert values to a Result, chain steps, replace errors, extract values, and provide two computation expressions for fallible steps.

dotnet add package Reified.Result

A first example

Verified
open System
open Reified.Result
open Reified.ResultDSL

type SignupError =
    | NameMissing
    | AgeNotANumber of string
    | AgeOutOfRange of int

let parseName (raw: string) =
    raw
    |> Result.failIf String.IsNullOrWhiteSpace
    |> Result.orError NameMissing

let parseAge (raw: string) =
    Int32.TryParse raw
    |> Result.fromTry
    |> Result.orError (AgeNotANumber raw)
    |> Result.bind (fun age ->
        if age >= 0 && age < 130 then Ok age else Error (AgeOutOfRange age))

result {
    let! name = parseName "Ada"
    let! age = parseAge "36"
    return {| Name = name; Age = age |}
}
Requires & types
Requires: open Reified.Result; open Reified.ResultDSL; open System (packages: Reified.Result)
val parseName: string -> Result<string,SignupError>
val parseAge: string -> Result<int,SignupError>
Ok { Name = "Ada"; Age = 36 }

Pages

Reified.Result composes failures. Constraints test typed values, Parsing decodes serialized primitives, and Refined constructs values whose types record a successful check. All three return the standard F# Result, so these helpers work on their output, but none requires this package, and this package does not require them.

Accumulation here is flat: result.list { } collects a list of your error values with no field identity. When a whole form, request, or document must become a model with path-aware accumulated diagnostics, that is Reified.Schema.