Safe Haskell | Safe |
---|---|

Language | Haskell2010 |

A data type similar to `Data.Either`

that accumulates failures.

- data AccValidation err a
- = AccFailure err
- | AccSuccess a

- validate :: Validate v => e -> (a -> Bool) -> a -> v e a
- validationNel :: Either e a -> AccValidation (NonEmpty e) a
- fromEither :: Either e a -> AccValidation e a
- liftError :: (b -> e) -> Either b a -> AccValidation e a
- validation :: (e -> c) -> (a -> c) -> AccValidation e a -> c
- toEither :: AccValidation e a -> Either e a
- orElse :: Validate v => v e a -> a -> a
- valueOr :: Validate v => (e -> a) -> v e a -> a
- ensure :: Validate v => e -> (a -> Bool) -> v e a -> v e a
- codiagonal :: AccValidation a a -> a
- validationed :: Validate v => (v e a -> v e' a') -> AccValidation e a -> AccValidation e' a'
- bindValidation :: AccValidation e a -> (a -> AccValidation e b) -> AccValidation e b
- _Failure :: Validate f => Prism (f e1 a) (f e2 a) e1 e2
- _Success :: Validate f => Prism (f e a) (f e b) a b
- class Validate f where
- revalidate :: (Validate f, Validate g) => Iso (f e1 s) (f e2 t) (g e1 s) (g e2 t)

# Data type

data AccValidation err a Source #

An `AccValidation`

is either a value of the type `err`

or `a`

, similar to `Either`

. However,
the `Applicative`

instance for `AccValidation`

*accumulates* errors using a `Semigroup`

on `err`

.
In contrast, the `Applicative`

for `Either`

returns only the first error.

A consequence of this is that `AccValidation`

has no `Bind`

or `Monad`

instance. This is because
such an instance would violate the law that a Monad's `ap`

must equal the
`Applicative`

's `<*>`

An example of typical usage can be found here.

AccFailure err | |

AccSuccess a |

Bifunctor AccValidation Source # | |

Bitraversable AccValidation Source # | |

Bifoldable AccValidation Source # | |

Swapped AccValidation Source # | |

Validate AccValidation Source # | |

Functor (AccValidation err) Source # | |

Semigroup err => Applicative (AccValidation err) Source # | |

Foldable (AccValidation err) Source # | |

Traversable (AccValidation err) Source # | |

Alt (AccValidation err) Source # | |

Semigroup err => Apply (AccValidation err) Source # | |

(Eq a, Eq err) => Eq (AccValidation err a) Source # | |

(Data a, Data err) => Data (AccValidation err a) Source # | |

(Ord a, Ord err) => Ord (AccValidation err a) Source # | |

(Show a, Show err) => Show (AccValidation err a) Source # | |

Semigroup e => Semigroup (AccValidation e a) Source # | |

Monoid e => Monoid (AccValidation e a) Source # | |

# Constructing validations

validate :: Validate v => e -> (a -> Bool) -> a -> v e a Source #

`validate`

s the `a`

with the given predicate, returning `e`

if the predicate does not hold.

This can be thought of as having the less general type:

validate :: e -> (a -> Bool) -> a -> AccValidation e a

validationNel :: Either e a -> AccValidation (NonEmpty e) a Source #

`validationNel`

is `liftError`

specialised to `NonEmpty`

lists, since
they are a common semigroup to use.

fromEither :: Either e a -> AccValidation e a Source #

Converts from `Either`

to `AccValidation`

.

liftError :: (b -> e) -> Either b a -> AccValidation e a Source #

`liftError`

is useful for converting an `Either`

to an `AccValidation`

when the `Left`

of the `Either`

needs to be lifted into a `Semigroup`

.

# Functions on validations

validation :: (e -> c) -> (a -> c) -> AccValidation e a -> c Source #

`validation`

is the catamorphism for `AccValidation`

.

toEither :: AccValidation e a -> Either e a Source #

Converts from `AccValidation`

to `Either`

.

orElse :: Validate v => v e a -> a -> a Source #

`v `

returns `orElse`

a`a`

when `v`

is AccFailure, and the `a`

in `AccSuccess a`

.

This can be thought of as having the less general type:

orElse :: AccValidation e a -> a -> a

valueOr :: Validate v => (e -> a) -> v e a -> a Source #

Return the `a`

or run the given function over the `e`

.

This can be thought of as having the less general type:

valueOr :: (e -> a) -> AccValidation e a -> a

ensure :: Validate v => e -> (a -> Bool) -> v e a -> v e a Source #

`ensure`

leaves the validation unchanged when the predicate holds, or
fails with `e`

otherwise.

This can be thought of as having the less general type:

ensure :: e -> (a -> Bool) -> AccValidation e a -> AccValidation e a

codiagonal :: AccValidation a a -> a Source #

`codiagonal`

gets the value out of either side.

validationed :: Validate v => (v e a -> v e' a') -> AccValidation e a -> AccValidation e' a' Source #

Run a function on anything with a Validate instance (usually Either) as if it were a function on AccValidation

This can be thought of as having the type

(Either e a -> Either e' a') -> AccValidation e a -> AccValidation e' a'

bindValidation :: AccValidation e a -> (a -> AccValidation e b) -> AccValidation e b Source #

`bindValidation`

binds through an AccValidation, which is useful for
composing AccValidations sequentially. Note that despite having a bind
function of the correct type, AccValidation is not a monad.
The reason is, this bind does not accumulate errors, so it does not
agree with the Applicative instance.

There is nothing wrong with using this function, it just does not make a
valid `Monad`

instance.

# Prisms

These prisms are useful for writing code which is polymorphic in its choice of Either or AccValidation. This choice can then be made later by a user, depending on their needs.

An example of this style of usage can be found here

_Failure :: Validate f => Prism (f e1 a) (f e2 a) e1 e2 Source #

This prism generalises `_Left`

. It targets the failure case of either `Either`

or `AccValidation`

.

_Success :: Validate f => Prism (f e a) (f e b) a b Source #

This prism generalises `_Right`

. It targets the success case of either `Either`

or `AccValidation`

.

# Isomorphisms

class Validate f where Source #

The `Validate`

class carries around witnesses that the type `f`

is isomorphic
to AccValidation, and hence isomorphic to Either.

_AccValidation :: Iso (f e a) (f g b) (AccValidation e a) (AccValidation g b) Source #

_Either :: Iso (f e a) (f g b) (Either e a) (Either g b) Source #

revalidate :: (Validate f, Validate g) => Iso (f e1 s) (f e2 t) (g e1 s) (g e2 t) Source #

`revalidate`

converts between any two instances of `Validate`

.