dataprep/validator
Types
Validator(a, e) checks a value and either returns it unchanged or produces errors. Key invariant: if v(x) returns Valid(y), then x == y.
pub type Validator(a, e) =
fn(a) -> validated.Validated(a, e)
Values
pub fn all(
validators: List(fn(a) -> validated.Validated(a, e)),
) -> fn(a) -> validated.Validated(a, e)
Run all validators on the same input. Accumulate all errors.
pub fn alt(
first v1: fn(a) -> validated.Validated(a, e),
second v2: fn(a) -> validated.Validated(a, e),
) -> fn(a) -> validated.Validated(a, e)
Try alternatives in order. Use when the input can satisfy different formats (e.g. UUID or slug).
Evaluation: v1 is tried first. If Valid, v2 is never called (short-circuit). If v1 fails, v2 is tried. If both fail, errors from both branches are accumulated.
The accumulated errors can be noisy for end-user display.
Use map_error to tag each branch before alt, then
post-process the error list before presenting to users.
pub fn both(
first v1: fn(a) -> validated.Validated(a, e),
second v2: fn(a) -> validated.Validated(a, e),
) -> fn(a) -> validated.Validated(a, e)
Run both validators on the same input. Accumulate all errors. On success, return the (unchanged) input.
pub fn check(
f: fn(a) -> Result(Nil, e),
) -> fn(a) -> validated.Validated(a, e)
Create a validator from a function that returns Ok(Nil) on success or Error(e) on failure. Allows value-dependent error construction.
pub fn each(
v: fn(a) -> validated.Validated(a, e),
) -> fn(List(a)) -> validated.Validated(List(a), e)
Validate each element of a list with the given validator. All errors from all elements are accumulated. Returns Valid with the unchanged list on success.
For index-aware validation, use validated.traverse_indexed
with validator.label to attach position info.
pub fn guard(
pre pre: fn(a) -> validated.Validated(a, e),
main main: fn(a) -> validated.Validated(a, e),
) -> fn(a) -> validated.Validated(a, e)
Short-circuit prerequisite. Use when main is expensive or semantically depends on pre passing (e.g. “non-empty” before “regex match”).
Evaluation: pre runs first. If Valid, main runs on the same input. If pre fails, main is never called and only pre’s errors are returned. Errors are NOT accumulated across pre and main.
pub fn label(
v: fn(a) -> validated.Validated(a, e1),
ctx: ctx,
wrap: fn(ctx, e1) -> e2,
) -> fn(a) -> validated.Validated(a, e2)
Attach structured context to all errors produced by a validator.
Shorthand for map_error(v, fn(e) { wrap(ctx, e) }).
Apply at module or field boundaries (once per field), not at every individual rule. Deeply nested labels produce unreadable error structures.
Example:
check_name |> validator.label(“name”, FieldError) // wraps every error e as FieldError(“name”, e)
pub fn map_error(
v: fn(a) -> validated.Validated(a, e1),
f: fn(e1) -> e2,
) -> fn(a) -> validated.Validated(a, e2)
Transform the error type of a validator.
pub fn optional(
v: fn(a) -> validated.Validated(a, e),
) -> fn(option.Option(a)) -> validated.Validated(
option.Option(a),
e,
)
Make a validator optional: if the value is None, it is always Valid(None). If Some(a), run the inner validator and wrap the result back in Some.
pub fn predicate(
condition: fn(a) -> Bool,
error: e,
) -> fn(a) -> validated.Validated(a, e)
Convenience for the common case of a boolean test with a static error.