packages feed

validators-0.0.1: README.md

# Validators

[![CircleCI](https://circleci.com/gh/luc-tielen/validators.svg?style=svg)](https://circleci.com/gh/luc-tielen/validators)

A library for validating input data in Haskell, inspired partly by [elm-validate](https://github.com/rtfeldman/elm-validate/).


## Concepts

### Validator

The library provides a `Validator` datatype for checking assertions
on input data. A validator is parametrized by 2 type variables:

1. `err`: the type of error a validator can return,
2. `subject`: the type being inspected/validated.

Execute validators by using the `validate` function:

```haskell
data Error = TooSmall | TooBig

>>> let validator = assert (> 10) [TooSmall]
>>> validate validator 11  -- Success 11
>>> validate validator 4   -- Failure [TooSmall]
```

Validators return a `Validation` type as result, which can be
further chained or checked for the final result. This is explained in
the [Validation](#Validation) section.

Validators can also be combined using the `Semigroup` instance,
resulting in a validator that accumulates errors from both sub-validators:

```haskell
>>> let validator = maxSize 3 [TooBig] <> minSize 2 [TooSmall]
>>> validate validator [1, 2, 3]     -- Success [1,2,3]
>>> validate validator [1, 2, 3, 4]  -- Failure [TooBig]
>>> validate validator [1]           -- Failure [TooSmall]
```

The library provides helper functions for commonly used validation checks.
See the docs for a complete overview which validators are available.


### Validation

Once a `Validator` has been executed, it will return a `Validation` data type.
This value will contain either all accumulated errors found during the checking
of assertions, or the given input value.

Validations are composed using their `Applicative` instance. This can be useful
for example when validating product types. Like with `Validator`, this will also
accumulate all encountered errors.

The following is an example for validating a `Person` data type:

```haskell
data PersonError = MissingName | InvalidAge

type Name = String
type Age = Int
data Person = Person Name Age

>>> let nameValidator = ifEmpty [MissingName]
>>> let ageValidator = assert (> 0) [InvalidAge]
>>> Person <$> validate nameValidator "" <*> validate ageValidator (subtract 1)       -- Failure [MissingName, InvalidAge]
>>> Person <$> validate nameValidator "Alice" <*> validate ageValidator (subtract 1)  -- Failure [InvalidAge]
>>> Person <$> validate nameValidator "Alice" <*> validate ageValidator 25            -- Success (Person "Alice" 25)
```


## Developing

The easiest way to start developing is by using [Nix](https://nixos.org/nix/download.html).

```bash
$ git clone git@github.com:luc-tielen/validators.git
$ cd validators
$ nix-shell
$ cabal new-configure  # run inside the nix-shell
$ cabal new-build      # run inside the nix-shell
```

The most often used commands are also provided by a [Makefile](https://github.com/luc-tielen/validators/blob/master/Makefile).