validator

Functions

all

pub fn all(
  validators: List(fn(a) -> Result(a, tuple(b, List(b)))),
) -> fn(a) -> Result(a, tuple(b, List(b)))

Validate a value using a list of validators. This runs all the validators in the list.

The initial input is passed to all validators. All these validators must have the same input and output types.

Returns Ok when all validators pass. Returns Error when any validator fails. Error will have all failures.

Example

let name_validator = v.all([
	v_string.is_not_empty("Empty"),
	v_string.min_length(">=3", 3),
	v_string.max_length("<=10", 10)
])

let validator = fn(person: Person) {
	v.build1(person)
	|> v.validate(person.name, name_validator)
}

and

pub fn and(
  validator1: fn(a) -> Result(b, tuple(c, List(c))),
  validator2: fn(b) -> Result(d, tuple(c, List(c))),
) -> fn(a) -> Result(d, tuple(c, List(c)))

Compose validators

Run the first validator and if successful then the second. Only returns the first error.

Example

let name_validator = v_string.is_not_empty("Empty")
|> v.and(v_string.min_length("Must be at least six", 6))

build1

pub fn build1(constructor: a) -> Result(a, b)

Build a validator for a type that has one attribute

Example

type Person { Person(name: String) }

let validator = fn(person: Person) {
	v.build1(person)
	|> v.validate(person.name, name_validator)
}

build2

pub fn build2(
  constructor: fn(a, b) -> c,
) -> Result(fn(a) -> fn(b) -> c, d)

Build a validator for a type that has two attributes

Example

type Person { Person(name: String, age: Int) }

let validator = fn(person: Person) {
	v.build2(person)
	|> v.validate(person.name, name_validator)
	|> v.validate(person.age, ...)
}

build3

pub fn build3(
  constructor: fn(a, b, c) -> d,
) -> Result(fn(a) -> fn(b) -> fn(c) -> d, e)

Build a validator for a type that has three attributes

Example

type Person { Person(name: String, age: Int, email: String) }

let validator = fn(person: Person) {
	v.build3(person)
	|> v.validate(person.name, name_validator)
	|> v.validate(person.age, ...)
	|> v.validate(person.email, ...)
}

build4

pub fn build4(
  constructor: fn(a, b, c, d) -> e,
) -> Result(fn(a) -> fn(b) -> fn(c) -> fn(d) -> e, f)

Build a validator for a type that has four attributes

build5

pub fn build5(
  constructor: fn(a, b, c, d, e) -> f,
) -> Result(fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> f, g)

Build a validator for a type that has five attributes

build6

pub fn build6(
  constructor: fn(a, b, c, d, e, f) -> g,
) -> Result(
  fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> g,
  h,
)

Build a validator for a type that has six attributes

custom

pub fn custom(
  error: a,
  check: fn(b) -> Option(c),
) -> fn(b) -> Result(c, tuple(a, List(a)))

Create a custom validator

A custom validator has two attributes:

  • The error
  • A check function

The check function is a function that takes an input and returns Option(output)

Example

let must_be_sam = fn(name: String) -> Option(String) {
	case name == "Sam" {
		True -> Some(name)
		False -> None
	}
}

let validator = fn(person: Person) {
	v.build1(Person)
	|> v.validate(person.name, v.custom("Not Sam", must_be_sam))
}

keep

pub fn keep(
  accumulator: Result(fn(a) -> b, tuple(c, List(c))),
  value: a,
) -> Result(b, tuple(c, List(c)))

Keep a value as is.

Example

fn person_validor(person: Person) {
	v.build2(Person)
		|> v.validate(person.name, ...)
		|> v.keep(person.age)
}

validate

pub fn validate(
  accumulator: Result(fn(a) -> b, tuple(c, List(c))),
  value: d,
  validator: fn(d) -> Result(a, tuple(c, List(c))),
) -> Result(b, tuple(c, List(c)))

Validate an attribute.

Example

let validator = fn(person: Person) {
	v.build1(Person)
	|> v.validate(person.name, v_string.is_not_empty(ErrorEmpty))
}

whole

pub fn whole(
  validator: fn(a) -> Result(a, b),
) -> fn(Result(a, tuple(b, List(b)))) ->
  Result(a, tuple(b, List(b)))

Validate a structure as a whole.

Sometimes we need to validate a property in relation to another.

This function requires a check function like:

fn(a) -> Result(a, error)

Example

let strengh_and_level_validator = fn(c: Character) {
	case c.level > c.strength {
		True -> Error(error)
		False -> Ok(c)
	}
}

let validator = fn(c: Character) {
	v.build2(Character)
	|> v.validate(c.level, v_int.min("Level must be more that zero", 1))
	|> v.validate(c.strength, v_int.min("Strength must be more that zero", 1))
	|> v.whole(strengh_and_level_validator)
}