-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Simple applicative validation for product types, batteries included! -- -- This package provides an applicative validator with support for -- contravariance. This makes building validators for product types -- idiomatic and simple. Many common utilities for building validators -- are also included. @package valida @version 1.0.0 -- | This module is re-exported by Valida. You probably don't need -- to import this. -- -- This module exports the primitive, as well as utility, -- Validator combinators. As well as the orElse, -- andAlso, satisfyAny, and satisfyAll functions, -- and some more utilities. -- -- Note: All the primitive combinators and derivative combinators -- use the same type for inp and a. In those cases - -- upon successful validation, the input itself, wrapped in -- Success, is returned. module Valida.Combinators -- | Build a rule that fails with given error if the given -- predicate succeeds. -- --
-- failureIf predc = failureUnless (not . predc) ---- --
-- >>> runValidator (failureIf (>0) "Positive") 5
-- Failure ("Positive" :| [])
--
-- >>> runValidator (failureIf (>0) "Positive") 0
-- Success 0
--
-- >>> runValidator (failureIf (>0) "Positive") (-1)
-- Success (-1)
--
failureIf :: (a -> Bool) -> e -> Validator (NonEmpty e) a a
-- | Build a rule that fails with given error unless the given
-- predicate succeeds.
--
-- -- failureUnless predc = failureIf (not . predc) ---- --
-- >>> runValidator (failureUnless (>0) "NonPositive") 5
-- Success 5
--
-- >>> runValidator (failureUnless (>0) "NonPositive") 0
-- Failure ("NonPositive" :| [])
--
-- >>> runValidator (failureUnless (>0) "NonPositive") (-1)
-- Failure ("NonPositive" :| [])
--
failureUnless :: (a -> Bool) -> e -> Validator (NonEmpty e) a a
-- | Like failureIf but uses Unit as the Validator
-- error type.
--
-- -- failureIf' predc = failureUnless' (not . predc) ---- --
-- label (const (err :| [])) (failureIf' predc) = failureIf predc err ---- --
-- >>> runValidator (failureIf' (>0)) 5 -- Failure () -- -- >>> runValidator (failureIf' (>0)) 0 -- Success 0 -- -- >>> runValidator (failureIf' (>0)) (-1) -- Success (-1) --failureIf' :: (a -> Bool) -> Validator () a a -- | Like failureUnless but uses Unit as the Validator -- error type. -- --
-- failureUnless' predc = failureIf' (not . predc) ---- --
-- label (const (err :| [])) (failureUnless' predc) = failureUnless predc err ---- --
-- >>> runValidator (failureUnless' (>0)) 5 -- Success 5 -- -- >>> runValidator (failureUnless' (>0)) 0 -- Failure () -- -- >>> runValidator (failureUnless' (>0)) (-1) -- Failure () --failureUnless' :: (a -> Bool) -> Validator () a a -- | Build a validator that succeeds if given validator fails and vice -- versa. -- -- Note: This will set the output of the Validator to be -- the same as its input, thereby ignoring the original output. -- --
-- >>> let vald = negateV "NonPositive" (failureIf (>0) "Positive") -- -- >>> runValidator vald 5 -- Success 5 -- -- >>> runValidator vald 0 -- Failure "NonPositive" -- -- >>> runValidator vald (-1) -- Failure "NonPositive" --negateV :: e -> Validator e1 a x -> Validator e a a -- | Like negateV but uses Unit as the Validator error -- type. negateV' :: Validator e a x -> Validator () a a -- | Build a validator that only succeeds if both of the -- given validators succeed. The first (left-most) failure is -- yielded. If both succeed, the right-most Success result -- is returned. Other validator is not used if first one fails. -- -- This is the same as the semigroup operation (i.e (<>)) on -- Validator. -- --
-- vald1 `andAlso` (vald2 `andAlso` vald3) = (vald1 `andAlso` vald2) `andAlso` vald3 ---- --
-- mempty `andAlso` vald = vald ---- --
-- vald `andAlso` mempty = vald ---- --
-- >>> let vald = failureIf (>0) "Positive" `andAlso` failureIf even "Even"
--
-- >>> runValidator vald 5
-- Failure ("Positive" :| [])
--
-- >>> runValidator vald (-2)
-- Failure ("Even" :| [])
--
-- >>> runValidator vald (-1)
-- Success (-1)
--
andAlso :: Validator e inp a -> Validator e inp a -> Validator e inp a
-- | Build a validator that succeeds if either of the given
-- validators succeed. The first (left-most) Success is returned.
-- If both fail, the errors are combined. Other validator is not
-- used if first one succeeds.
--
-- -- vald1 `orElse` (vald2 `orElse` vald3) = (vald1 `orElse` vald2) `orElse` vald3 ---- --
-- failV e `orElse` vald = vald ---- --
-- vald `orElse` failV e = vald ---- --
-- >>> let vald = failureIf (>0) "Positive" `orElse` failureIf even "Even"
--
-- >>> runValidator vald 5
-- Success 5
--
-- >>> runValidator vald 4
-- Failure ("Positive" :| ["Even"])
--
-- >>> runValidator vald 0
-- Success 0
--
-- >>> runValidator vald (-1)
-- Success (-1)
--
orElse :: Semigroup e => Validator e inp a -> Validator e inp a -> Validator e inp a
-- | A Validator that always fails with supplied error. This is the
-- identity of orElse (i.e (</>)).
--
-- -- failV `orElse` vald = vald ---- --
-- vald `orElse` failV = vald ---- --
-- >>> runValidator (failV :: Validator String Int Int) 42 -- Failure "" --failV :: Monoid e => Validator e inp a -- | Build a validator that only succeeds if all of the given -- validators succeed. The first (left-most) failure is yielded. -- If all succeed, the right-most Success result is -- returned. Remaining validators are not used once one fails. -- --
-- satisfyAll = fold ---- --
-- satisfyAll = foldl1 andAlso ---- --
-- satisfyAll = foldr1 andAlso ---- --
-- satisfyAll = foldl andAlso mempty ---- --
-- satisfyAll = foldr andAlso mempty --satisfyAll :: Foldable t => t (Validator e inp a) -> Validator e inp a -- | Build a validator that succeeds if any of the given -- validators succeed. If all fail, the errors are combined. The first -- (left-most) Success is returned. If all fail, the errors -- are combined. Remaining validators are not used once one -- succeeds. -- --
-- satisfyAny = foldl1 orElse ---- --
-- satisfyAny = foldr1 orElse ---- --
-- satisfyAny = foldl orElse failV ---- --
-- satisfyAny = foldr orElse failV --satisfyAny :: (Foldable t, Semigroup e) => t (Validator e inp a) -> Validator e inp a -- | A synonym for orElse. Satisfies associativity law and hence -- forms a semigroup. (>) :: Semigroup e => Validator e inp a -> Validator e inp a -> Validator e inp a infixr 5 > -- | Build an any rule. -- --
-- atleastContains x = failureUnless (any x) --atleastContains :: Foldable t => (a -> Bool) -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a minimum length (inclusive) rule. -- --
-- lengthAbove x = minLengthOf (x + 1) ---- --
-- lengthAbove x = failureUnless ((>n) . length) --lengthAbove :: Foldable t => Int -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a maximum length (inclusive) rule. -- --
-- lengthBelow x = maxLengthOf (x - 1) ---- --
-- lengthBelow x = failureUnless ((<n) . length) --lengthBelow :: Foldable t => Int -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build an inRange rule for length. -- --
-- lengthWithin (min, max) = minLengthOf min `andAlso` maxLengthOf max ---- --
-- lengthWithin r = failureUnless (inRange r . length) --lengthWithin :: Foldable t => (Int, Int) -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a maximum length (inclusive) rule. -- --
-- maxLengthOf n = failureUnless ((<=n) . length) --maxLengthOf :: Foldable t => Int -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a maximum value (inclusive) rule. -- --
-- maxValueOf x = failureUnless (<=x) --maxValueOf :: Ord a => a -> e -> Validator (NonEmpty e) a a -- | Build a minimum length (inclusive) rule. -- --
-- minLengthOf x = failureUnless ((>=n) . length) --minLengthOf :: Foldable t => Int -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a minimum value (inclusive) rule. -- --
-- minValueOf x = failureUnless (>=x) --minValueOf :: Ord a => a -> e -> Validator (NonEmpty e) a a -- | Build an equality rule for value. -- --
-- mustBe x = failureUnless (==x) --mustBe :: Eq a => a -> e -> Validator (NonEmpty e) a a -- | Build an elem rule. -- --
-- mustContain x = atleastContains (==x) ---- --
-- mustContain x = failureUnless (elem x) --mustContain :: (Foldable t, Eq a) => a -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a maximum length rule. -- --
-- notEmpty = minLengthOf 1 ---- --
-- notEmpty = failureIf null --notEmpty :: Foldable t => e -> Validator (NonEmpty e) (t a) (t a) -- | Build an equality rule for length. -- --
-- ofLength x = failureUnless ((==x) . length) --ofLength :: Foldable t => Int -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build an all rule. -- --
-- onlyContains x = failureUnless (all x) --onlyContains :: Foldable t => (a -> Bool) -> e -> Validator (NonEmpty e) (t a) (t a) -- | Build a minimum value (exclusive) rule. -- --
-- valueAbove x = minValueOf (x + 1) ---- --
-- valueAbove x = failureUnless (>x) --valueAbove :: Ord a => a -> e -> Validator (NonEmpty e) a a -- | Build a maximum value (exclusive) rule. -- --
-- valueBelow x = minValueOf (x - 1) ---- --
-- valueBelow x = failureUnless (<x) --valueBelow :: Ord a => a -> e -> Validator (NonEmpty e) a a -- | Build an inRange rule for value. -- --
-- valueWithin (m, n) = minValueOf m `andAlso` maxValueOf n ---- --
-- valueWithin (m, n) = failureUnless (x -> m <= x && x <= n) --valueWithin :: Ord a => (a, a) -> e -> Validator (NonEmpty e) a a -- | Like atleastContains but uses Unit as the -- Validator error type. atleastContains' :: Foldable t => (a -> Bool) -> Validator () (t a) (t a) -- | Like lengthAbove but uses Unit as the Validator -- error type. lengthAbove' :: Foldable t => Int -> Validator () (t a) (t a) -- | Like lengthBelow but uses Unit as the Validator -- error type. lengthBelow' :: Foldable t => Int -> Validator () (t a) (t a) -- | Like lengthWithin but uses Unit as the Validator -- error type. lengthWithin' :: Foldable t => (Int, Int) -> Validator () (t a) (t a) -- | Like maxLengthOf but uses Unit as the Validator -- error type. maxLengthOf' :: Foldable t => Int -> Validator () (t a) (t a) -- | Like maxValueOf but uses Unit as the Validator -- error type. maxValueOf' :: Ord a => a -> Validator () a a -- | Like minLengthOf but uses Unit as the Validator -- error type. minLengthOf' :: Foldable t => Int -> Validator () (t a) (t a) -- | Like minValueOf but uses Unit as the Validator -- error type. minValueOf' :: Ord a => a -> Validator () a a -- | Like mustBe but uses Unit as the Validator error -- type. mustBe' :: Eq a => a -> Validator () a a -- | Like mustContain but uses Unit as the Validator -- error type. mustContain' :: (Foldable t, Eq a) => a -> Validator () (t a) (t a) -- | Like notEmpty but uses Unit as the Validator -- error type. notEmpty' :: Foldable t => Validator () (t a) (t a) -- | Like ofLength but uses Unit as the Validator -- error type. ofLength' :: Foldable t => Int -> Validator () (t a) (t a) -- | Like onlyContains but uses Unit as the Validator -- error type. onlyContains' :: Foldable t => (a -> Bool) -> Validator () (t a) (t a) -- | Like valueAbove but uses Unit as the Validator -- error type. valueAbove' :: Ord a => a -> Validator () a a -- | Like valueBelow but uses Unit as the Validator -- error type. valueBelow' :: Ord a => a -> Validator () a a -- | Like valueWithin but uses Unit as the Validator -- error type. valueWithin' :: Ord a => (a, a) -> Validator () a a -- | Build a validator that runs given validator only if input is -- Just. -- -- Yields Success when input is Nothing. -- --
-- >>> runValidator (optionally (failureIf even "Even")) (Just 5)
-- Success (Just 5)
--
-- >>> runValidator (optionally (failureIf even "Even"))) (Just 6)
-- Failure ("Even" :| [])
--
-- >>> runValidator (optionally (failureIf even "Even")) Nothing
-- Success Nothing
--
optionally :: Validator e a x -> Validator e (Maybe a) (Maybe a)
-- | This module exports the primary validator building functions. It also
-- exports all of Valida.Combinators.
--
-- For a full tutorial, check out the README at
-- https://github.com/TotallyNotChase/valida#readme. Refer to the
-- hackage documentation for function reference and examples.
--
-- You can also find more examples within the examples directory in
-- linked github repo.
module Valida
-- | Like Either, but accumulates failures upon applicative
-- composition.
data Validation e a
-- | Represents a validation failure with an error.
Failure :: e -> Validation e a
-- | Represents a successful validation with the validated value.
Success :: a -> Validation e a
-- | An applicative validator. Validates a predicate on an input when run
-- and returns the Validation result.
--
-- The type can be understood as-
--
-- -- Validator e inp a -- ^ ^ ^------ The output type on successful validation -- | | -- Error type |-- The input on which validation is run ---- -- Validators are run using the runValidator function. The result -- is of type Validation e a, corresponding to the type params of -- the same name on Validator. -- -- Note: All the primitive combinators (and derivative -- combinators) use the same type for inp and a. In -- those cases - upon successful validation, the input itself, wrapped in -- Success, is returned. data Validator e inp a -- | Fix a validator's output to be the same as its input. -- --
-- fixV . fixV = id . fixV ---- --
-- fmap (const x) . fixV = fmap (const x) ---- -- Note: The primitive and derivative combinators already fix the -- validator output to be the same as its input. -- --
-- >>> let evenValidator = failureIf even "Even" ---- -- This validator, when run, will yield its input value, wrapped in -- Success, if input is not even. fixV would be redundant -- on this. -- -- However, if the output was fmaped to be something else- -- --
-- >>> let evenValidator' = fmap (:[]) evenValidator ---- -- Now the output type is `[Int]`. The value of the output is no longer -- the same as the input. If we needed to get the original input back -- into the output, fixV would be the right choice. -- --
-- >>> let evenValidator'' = fixV evenValidator' ---- -- evenValidator'' is now the exact same as evenValidator, which was -- fixed from the start. -- --
-- >>> (("foo" <$ failureIf even "Even") <> ("bar" <$ failureIf (<0) "Negative")) `runValidator` 5
-- Success "bar"
--
-- >>> fixV (("foo" <$ failureIf even "Even") <> ("bar" <$ failureIf (<0) "Negative")) `runValidator` 5
-- Success 5
--
fixV :: Validator e a x -> Validator e a a
-- | An alias to lmap specialized to Validator.
--
-- verify allows a validator taking input b to work with
-- input a, provided a function of type: a -> b.
--
-- The new Validator first runs the selector on its input
-- to obtain the validation target. Then, it runs the predicate on the
-- target.
--
-- If validation is successful, the the *original* output is put into the
-- Validation result.
--
-- -- >>> let pairValidator = (,) <$> verify (notEmpty "EmptyString") fst <*> verify (failureIf (<10) "LessThan10") snd ---- -- You can then run the validator on your input, using -- runValidator: -- --
-- >>> runValidator pairValidator ("foo", 12)
-- Success ("foo",12)
--
-- >>> runValidator pairValidator ("", 12)
-- Failure ("EmptyString" :| [])
--
-- >>> runValidator pairValidator ("foo", 9)
-- Failure ("LessThan10" :| [])
--
-- >>> runValidator pairValidator ("", 9)
-- Failure ("EmptyString" :| ["LessThan10"])
--
verify :: Validator e b x -> (a -> b) -> Validator e a x
-- | A synonym for verify with its arguments flipped.
(-?>) :: (a -> b) -> Validator e b x -> Validator e a x
infix 5 -?>
-- | Relabel a Validator with a different error.
--
-- -- >>> let validator = label "NotEven" (failureUnless' even) -- -- >>> runValidator validator 1 -- Failure "NotEven" ---- --
-- >>> let validator = label "DefinitelyNotEven" (failureUnless even "NotEven") -- -- >>> runValidator validator 1 -- Failure "DefinitelyNotEven" --label :: e -> Validator x inp a -> Validator e inp a -- | A synonym for label with its arguments flipped. (>) :: Validator x inp a -> e -> Validator e inp a infix 6 > -- | Convert a Either to an Validation. -- -- Given, Either e a- -- --
-- >>> fromEither (Right 'c' :: Either String Char) -- Success 'c' -- -- >>> fromEither (Left 42 :: Either Int Char) -- Failure 42 --fromEither :: Either e a -> Validation e a -- | Convert a Validation to an Either. -- -- Given, Validation a b- -- --
-- >>> toEither (Success 'c' :: Validation String Char) -- Right 'c' -- -- >>> toEither (Failure 42 :: Validation Int Char) -- Left 42 --toEither :: Validation a b -> Either a b -- | Case analysis for Validation, i.e catamorphism. -- -- In case of 'Failure e', apply the first function to e; in case of -- 'Success a', apply the second function to a. -- -- This is a more generalized version of the bifoldMap -- implementation. -- --
-- >>> validation (const Nothing) Just (Success 'c' :: Validation String Char) -- Just 'c' -- -- >>> validation (const Nothing) Just (Failure "error" :: Validation String Char) -- Nothing --validation :: (e -> c) -> (a -> c) -> Validation e a -> c -- | Case analysis for Validation, with replacer. -- -- This is similar to validation, but takes in replacers instead -- of functions. -- -- In case of Failure, return the first argument; otherwise, -- return the second argument. -- --
-- validationConst e a = validation (const e) (const a) ---- --
-- >>> validation (const Nothing) Just (Success 'c' :: Validation String Char) -- Just 'c' -- -- >>> validation (const Nothing) Just (Failure "error" :: Validation String Char) -- Nothing --validationConst :: p -> p -> Validation e a -> p -- | Return the contents of a Success-value or a default value -- otherwise. -- --
-- >>> fromSuccess 0 (Success 48 :: Validation Int Int) -- 48 -- -- >>> fromSuccess 0 (Failure 27 :: Validation Int Int) -- 0 --fromSuccess :: a -> Validation e a -> a -- | Return the contents of a Failure-value or a default value -- otherwise. -- --
-- >>> fromFailure 0 (Success 48 :: Validation Int Int) -- 0 -- -- >>> fromFailure 0 (Failure 27 :: Validation Int Int) -- 27 --fromFailure :: e -> Validation e a -> e -- | Return True if the given value is a Success-value, False -- otherwise. isSuccess :: Validation e a -> Bool -- | Return True if the given value is a Failure-value, False -- otherwise. isFailure :: Validation e a -> Bool -- | Extracts from a list of Validation all the Success elements, in -- order. -- --
-- >>> successes [Success 1, Failure "err1", Failure "err2", Success 2, Failure "err3"] -- [1,2] -- -- >>> successes ([Failure "err1", Failure "err2", Failure "err3"] :: [Validation String Int]) -- [] --successes :: [Validation e a] -> [a] -- | Extracts from a list of Validation all the Failure -- values, in order. -- --
-- >>> failures [Success 48, Failure "err1", Failure "err2", Success 2, Failure "err3"] -- ["err1","err2","err3"] -- -- >>> failures ([Success 1, Success 2, Success 3] :: [Validation String Int]) -- [] --failures :: [Validation e a] -> [e] -- | Partitions a list of Either into two lists. -- -- All the Left elements are extracted, in order, to the first component -- of the output. Similarly the Right elements are extracted to the -- second component of the output. -- --
-- partitionValidations xs = (failures xs, successes xs) ---- --
-- >>> partitionValidations [Success 1, Failure "err1", Failure "err2", Success 2, Failure "err3"] -- (["err1","err2","err3"],[1,2]) --partitionValidations :: [Validation e a] -> ([e], [a])