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

Handling errors

Map an error, replace it, or use it to produce a fallback.

Verified
open Reified.Result

type SignupError =
    | NameMissing
    | AgeMissing

Changing the error

mapError transforms whatever the error carries. Use it when the existing error holds something worth keeping.

Verified
Error NameMissing |> Result.mapError (fun _ -> "name is required")
// Error "name is required"
Requires & types
Requires: open Reified.Result (packages: Reified.Result)

orError discards the existing error and substitutes yours. Use it when the incoming error carries nothing, the unit from okIf, failIf, or fromTry, or a low-level detail the caller should not see.

Verified
Error "index out of range" |> Result.orError NameMissing
// Error NameMissing
Requires & types
Requires: open Reified.Result (packages: Reified.Result)

Recovering

orElse supplies a fallback result when the first one fails. The fallback is an already-computed value.

Verified
(Error AgeMissing: Result<int, SignupError>) |> Result.orElse (Ok 0)
// Ok 0

Ok 36 |> Result.orElse (Ok 0)
// Ok 36
Requires & types
Requires: open Reified.Result (packages: Reified.Result)

orElseWith computes the fallback from the error, and only on failure. Use it when the fallback is expensive, or when which fallback to use depends on why the first attempt failed.

Verified
(Error AgeMissing: Result<int, SignupError>) |> Result.orElseWith (fun _ -> Ok 0)
// Ok 0
Requires & types
Requires: open Reified.Result (packages: Reified.Result)

Both keep the error type the same. If a recovery step fails with a different error type, convert with mapError first so both sides agree.

Choosing between them

Situation Function
the error carries something worth keeping mapError
the error is unit or an internal detail orError
a fallback value is already to hand orElse
the fallback is expensive or depends on the error orElseWith