validated
This module provides the Validated
type and associated functions
to accumulate errors in an ergonomic way.
Example
fn validate_form(email: String, age: Int) -> Validated(Form, String) {
use email <- v.do(validate_email(email))
use age <- v.do(validate_age(age))
Valid(Form(email:, age:))
}
validated_form("lucy@example.com", 20)
// -> Valid(Form("lucy@example.com", 20))
validated_form("asdf", 5)
// -> Invalid(Form("", 0), ["not a valid email", "must be 18 or older"])
This API is possible because a Validated
requires a “default” value
in case of failure. That way, the default value is passed through to
continue the validation.
Since a value within a validation block may or may not be the default value, it is important to never perform side-effects inside the validation.
Types
Validated
represents the result of something that may succeed or not.
It is similar to Result
, except that it will accumulate multiple errors
instead of stopping at the first error.
Valid
means it was successful, Invalid
means it was not successful.
pub type Validated(a, e) {
Valid(a)
Invalid(a, List(e))
}
Constructors
-
Valid(a)
-
Invalid(a, List(e))
Invalid requires a default value to enable validation in
use
expressions
Functions
pub fn all(
validateds: List(Validated(a, b)),
) -> Validated(List(a), b)
Combines a list of Validateds
into a single Validated
.
If all elements in the list are Valid
then the function returns a Valid
holding the list of values.
Otherwise an Invalid
is returned that combines all the errors.
Valid([])
is returned if the list is empty.
pub fn bit_array(
value: Result(BitArray, a),
) -> Validated(BitArray, a)
Creates a Validated
from a Result
.
It uses an empty BitArray
as the default value in case of failure.
pub fn bool(value: Result(Bool, a)) -> Validated(Bool, a)
Creates a Validated
from a Result
.
It uses False
as the default value in case of failure.
pub fn dict(
value: Result(Dict(a, b), c),
) -> Validated(Dict(a, b), c)
Creates a Validated
from a Result
.
It uses an empty Dict
as the default value in case of failure.
pub fn do(
validated: Validated(a, b),
next: fn(a) -> Validated(c, b),
) -> Validated(c, b)
“Updates” a Valid
value by passing its value to a function that yields a Validated
,
and returning the yielded Validated
. (This may “replace” the Valid
with an Invalid
.)
If the input is an Invalid
rather than an Valid
, the function is still called using the default
value from the Invalid
. If the function succeeds, the Invalid
’s default is replaced with the Valid
value.
If the function fails, the first Invalid
errors are combined with the returned Invalid
errors.
This function is useful in use
expressions to ergonomically validate fields of a record
Examples
use a <- do(Valid(1))
use b <- do(Valid(2))
Valid(#(a, b))
// -> Valid(#(1, 2))
use a <- do(Invalid(0, [Nil]))
use b <- do(Valid(2))
use c <- do(Invalid(0, [Nil]))
Valid(#(a, b, c))
// -> Invalid(#(0, 2, 0), [Nil, Nil])
pub fn flatten(
validated: Validated(Validated(a, b), b),
) -> Validated(a, b)
Merges a nested Validated
into a single layer.
pub fn float(value: Result(Float, a)) -> Validated(Float, a)
Creates a Validated
from a Result
.
It uses 0.0
as the default value in case of failure.
pub fn guard(
validated: Validated(a, b),
default: c,
continue: fn(a) -> Validated(c, b),
) -> Validated(c, b)
Like do
, but does not continue accumulating further errors if the
Validated
is Invalid
.
pub fn int(value: Result(Int, a)) -> Validated(Int, a)
Creates a Validated
from a Result
.
It uses 0
as the default value in case of failure.
pub fn is_invalid(validated: Validated(a, b)) -> Bool
Checks whether the Validated
is Invalid
pub fn is_valid(validated: Validated(a, b)) -> Bool
Checks whether the Validated
is Valid
pub fn lazy_guard(
validated: Validated(a, b),
default: fn() -> c,
continue: fn(a) -> Validated(c, b),
) -> Validated(c, b)
Like guard
but accepts a callback for the default value in case the
Validated
is Invalid
.
pub fn list(value: Result(List(a), b)) -> Validated(List(a), b)
Creates a Validated
from a Result
.
It uses an empty list as the default value in case of failure.
pub fn map(
validated: Validated(a, b),
f: fn(a) -> c,
) -> Validated(c, b)
Updates a value held within the Valid
of a Validated
by calling a given function on it.
If the Validated
is an Invalid
rather than Valid
, the function is called on the default value.
pub fn map_error(
validated: Validated(a, b),
f: fn(List(b)) -> List(c),
) -> Validated(a, c)
Updates a value held within the Invalid
of a Validated
by calling a given function on it.
If the result is Valid
rather than Invalid
the function is not called and the result stays the same.
pub fn optional(
value: Result(Option(a), b),
) -> Validated(Option(a), b)
Creates a Validated
from a Result
.
It uses None
as the default value in case of failure.
pub fn replace(
validated: Validated(a, b),
value: c,
) -> Validated(c, b)
Replace the value within a Validated
pub fn result(value: Result(a, b), default: a) -> Validated(a, b)
Creates a Validated
from a Result
.
It requires a default value in case of failure.
pub fn run(
validator: fn(a) -> Validated(b, c),
input: a,
) -> Validated(b, c)
Run a Validator
function.
pub fn run_all(
validators: List(fn(a) -> Validated(b, c)),
input: a,
) -> Validated(Nil, c)
Run all the Validators
in order on the given input.
It will accumulate all the errors from all of the Validators
.
If there are no errors, or if the list is empty, Valid(Nil)
is returned.
pub fn string(value: Result(String, a)) -> Validated(String, a)
Creates a Validated
from a Result
.
It uses an empty string as the default value in case of failure.
pub fn to_result(
validated: Validated(a, b),
) -> Result(a, List(b))
Convert a Validated
into a Result