rectify

Rectify - Railway-oriented programming utilities for Gleam

A port of FsToolkit.ErrorHandling concepts:

Types

Validation applicative - collect multiple errors instead of fail-fast.

Unlike Result which stops at the first Error, Validation accumulates all errors before returning them together.

pub type Validation(a, e) {
  Valid(a)
  Invalid(List(e))
}

Constructors

  • Valid(a)
  • Invalid(List(e))

Values

pub fn apply(
  vf: Validation(fn(a) -> b, e),
  va: Validation(a, e),
) -> Validation(b, e)

Apply a validation containing a function to a validation containing a value.

Examples

apply(valid(fn(x) { x * 2 }), valid(21))
// -> Valid(42)
apply(invalid("e1"), invalid("e2"))
// -> Invalid(["e1", "e2"])
pub fn bind(
  v: Validation(a, e),
  f: fn(a) -> Validation(b, e),
) -> Validation(b, e)

Bind/flatMap for validation (note: doesn’t accumulate errors across binds).

Use this when determining the next validation step depends on the success value of the previous step. Errors from the first step are preserved, but errors do not accumulate with operations in the second step, because the second step is never executed if the first step fails.

Examples

valid(1) |> bind(fn(x) { valid(x * 2) })
// -> Valid(2)
invalid("e") |> bind(fn(x) { valid(x * 2) })
// -> Invalid(["e"])
pub fn default_to(v: Validation(a, e), default: a) -> a

Run a validation and return the value or a default.

Examples

default_to(valid(42), 0)
// -> 42
default_to(invalid("e"), 0)
// -> 0
pub fn default_with(v: Validation(a, e), f: fn() -> a) -> a

Run a validation with a lazy default.

Examples

default_with(valid(42), fn() { 0 })
// -> 42
default_with(invalid("e"), fn() { 0 })
// -> 0
pub fn errors(v: Validation(a, e)) -> List(e)

Get errors from a validation, or empty list if Valid.

Examples

errors(valid(1))
// -> []
errors(invalid_many(["a", "b"]))
// -> ["a", "b"]
pub fn flatten(
  v: Validation(Validation(a, e), e),
) -> Validation(a, e)

Flatten a nested validation.

Examples

flatten(valid(valid(1)))
// -> Valid(1)
flatten(valid(invalid("e")))
// -> Invalid(["e"])
pub fn invalid(e: e) -> Validation(a, e)

Create a failed validation with a single error.

pub fn invalid_many(es: List(e)) -> Validation(a, e)

Create a failed validation with multiple errors.

pub fn is_invalid(v: Validation(a, e)) -> Bool

Check if validation has errors.

Examples

is_invalid(invalid("e"))
// -> True
is_invalid(valid(1))
// -> False
pub fn is_valid(v: Validation(a, e)) -> Bool

Check if validation is valid.

Examples

is_valid(valid(1))
// -> True
is_valid(invalid("e"))
// -> False
pub fn map(
  validation: Validation(a, e),
  f: fn(a) -> b,
) -> Validation(b, e)

Map a function over a validation.

Examples

valid(5) |> map(fn(n) { n * 2 })
// -> Valid(10)
invalid("error") |> map(fn(n) { n * 2 })
// -> Invalid(["error"])
pub fn map2(
  v1: Validation(a, e),
  v2: Validation(b, e),
  f: fn(a, b) -> c,
) -> Validation(c, e)

Map over two validations, combining their errors if both fail.

Examples

map2(valid(2), valid(3), fn(a, b) { a + b })
// -> Valid(5)
map2(invalid("e1"), invalid("e2"), fn(a, b) { a + b })
// -> Invalid(["e1", "e2"])
pub fn map3(
  v1: Validation(a, e),
  v2: Validation(b, e),
  v3: Validation(c, e),
  f: fn(a, b, c) -> d,
) -> Validation(d, e)

Map over three validations.

Similar to map2, but for three validations. Gathers all errors if any of the validations are invalid.

pub fn map4(
  v1: Validation(a, e),
  v2: Validation(b, e),
  v3: Validation(c, e),
  v4: Validation(d, e),
  f: fn(a, b, c, d) -> g,
) -> Validation(g, e)

Map over four validations.

Similar to map2, but for four validations. Gathers all errors if any of the validations are invalid.

pub fn map5(
  v1: Validation(a, e),
  v2: Validation(b, e),
  v3: Validation(c, e),
  v4: Validation(d, e),
  v5: Validation(g, e),
  f: fn(a, b, c, d, g) -> h,
) -> Validation(h, e)

Map over five validations.

Similar to map2, but for five validations. Gathers all errors if any of the validations are invalid.

pub fn map_errors(
  v: Validation(a, e),
  f: fn(e) -> f,
) -> Validation(a, f)

Transform errors in a validation.

Examples

invalid("e") |> map_errors(fn(e) { "Error: " <> e })
// -> Invalid(["Error: e"])
pub fn of_result(r: Result(a, e)) -> Validation(a, e)

Convert Result to Validation.

Examples

of_result(Ok(42))
// -> Valid(42)
of_result(Error("e"))
// -> Invalid(["e"])
pub fn of_result_list(r: Result(a, List(e))) -> Validation(a, e)

Convert Result with multiple errors to Validation.

Examples

of_result_list(Ok(42))
// -> Valid(42)
of_result_list(Error(["e1", "e2"]))
// -> Invalid(["e1", "e2"])
pub fn to_result(v: Validation(a, e)) -> Result(a, List(e))

Convert validation to Result (all errors as list).

Examples

to_result(valid(42))
// -> Ok(42)
to_result(invalid_many(["a", "b"]))
// -> Error(["a", "b"])
pub fn valid(a: a) -> Validation(a, e)

Create a successful validation.

Search Document