-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Simple applicative validation for product types, batteries included! -- -- This is a zero dependency version of the valida package. It is -- equivalent to valida == 0.1.0. Check out the README at github -- https://github.com/TotallyNotChase/valida-base#readme! @package valida-base @version 0.2.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, -- ValidationRule combinators. As well as the orElse, -- andAlso, satisfyAny, and satisfyAll functions, -- and some more utilities. module Valida.Combinators -- | Build a rule that fails with given error if the given -- predicate succeeds. -- --
-- failureIf predc = failureUnless (not . predc) ---- --
-- >>> runValidator (validate (failureIf (>0) "Positive")) 5
-- Failure ("Positive" :| [])
--
-- >>> runValidator (validate (failureIf (>0) "Positive")) 0
-- Success 0
--
-- >>> runValidator (validate (failureIf (>0) "Positive")) (-1)
-- Success (-1)
--
failureIf :: (a -> Bool) -> e -> ValidationRule (NonEmpty e) a
-- | Build a rule that fails with given error unless the given
-- predicate succeeds.
--
-- -- failureUnless predc = failureIf (not . predc) ---- --
-- >>> runValidator (validate (failureUnless (>0) "NonPositive")) 5
-- Success 5
--
-- >>> runValidator (validate (failureUnless (>0) "NonPositive")) 0
-- Failure ("NonPositive" :| [])
--
-- >>> runValidator (validate (failureUnless (>0) "NonPositive")) (-1)
-- Failure ("NonPositive" :| [])
--
failureUnless :: (a -> Bool) -> e -> ValidationRule (NonEmpty e) a
-- | Like failureIf but uses Unit as the
-- ValidationRule error type.
--
-- -- failureIf' predc = failureUnless' (not . predc) ---- --
-- label (const (err :| [])) (failureIf' predc) = failureIf predc err ---- --
-- >>> runValidator (validate (failureIf' (>0))) 5 -- Failure () -- -- >>> runValidator (validate (failureIf' (>0))) 0 -- Success 0 -- -- >>> runValidator (validate (failureIf' (>0))) (-1) -- Success (-1) --failureIf' :: (a -> Bool) -> ValidationRule () a -- | Like failureUnless but uses Unit as the -- ValidationRule error type. -- --
-- failureUnless' predc = failureIf' (not . predc) ---- --
-- label (const (err :| [])) (failureUnless' predc) = failureUnless predc err ---- --
-- >>> runValidator (validate (failureUnless' (>0))) 5 -- Success 5 -- -- >>> runValidator (validate (failureUnless' (>0))) 0 -- Failure () -- -- >>> runValidator (validate (failureUnless' (>0))) (-1) -- Failure () --failureUnless' :: (a -> Bool) -> ValidationRule () a -- | Build a rule that succeeds if given rule fails and vice versa. -- --
-- >>> let rule = negateRule "NonPositive" (failureIf (>0) "Positive") -- -- >>> runValidator (validate rule) 5 -- Success 5 -- -- >>> runValidator (validate rule) 0 -- Failure "NonPositive" -- -- >>> runValidator (validate rule) (-1) -- Failure "NonPositive" --negateRule :: e -> ValidationRule e1 a -> ValidationRule e a -- | Like negateRule but uses Unit as the -- ValidationRule error type. negateRule' :: ValidationRule e a -> ValidationRule () a -- | Build a rule that only succeeds if both of the given -- rules succeed. The very first failure is yielded. -- -- This is the same as the semigroup operation (i.e (<>)) on -- ValidationRule. -- --
-- rule1 `andAlso` (rule2 `andAlso` rule3) = (rule1 `andAlso` rule2) `andAlso` rule3 ---- --
-- mempty `andAlso` rule = rule ---- --
-- rule `andAlso` mempty = rule ---- --
-- >>> let rule = failureIf (>0) "Positive" `andAlso` failureIf even "Even"
--
-- >>> runValidator (validate rule) 5
-- Failure ("Positive" :| [])
--
-- >>> runValidator (validate rule) (-2)
-- Failure ("Even" :| [])
--
-- >>> runValidator (validate rule) (-1)
-- Success (-1)
--
andAlso :: ValidationRule e a -> ValidationRule e a -> ValidationRule e a
-- | A ValidationRule that always fails with supplied error. This is
-- the identity of orElse (i.e (</>)).
--
-- -- falseRule `orElse` rule = rule ---- --
-- rule `orElse` falseRule = rule ---- --
-- >>> runValidator (validate falseRule) 42 -- Failure () --falseRule :: Monoid e => ValidationRule e a -- | Build a rule that succeeds if either of the given rules -- succeed. If both fail, the errors are combined. -- --
-- rule1 `orElse` (rule2 `orElse` rule3) = (rule1 `orElse` rule2) `orElse` rule3 ---- --
-- falseRule e `orElse` rule = rule ---- --
-- rule `orElse` falseRule e = rule ---- --
-- >>> let rule = failureIf (>0) "Positive" `orElse` failureIf even "Even"
--
-- >>> runValidator (validate rule) 5
-- Success 5
--
-- >>> runValidator (validate rule) 4
-- Failure ("Positive" :| ["Even"])
--
-- >>> runValidator (validate rule) 0
-- Success 0
--
-- >>> runValidator (validate rule) (-1)
-- Success (-1)
--
orElse :: Semigroup e => ValidationRule e a -> ValidationRule e a -> ValidationRule e a
-- | Build a rule that only succeeds if all of the given
-- rules succeed. The very first failure is yielded.
--
-- -- satisfyAll = fold ---- --
-- satisfyAll = foldl1 andAlso ---- --
-- satisfyAll = foldr1 andAlso ---- --
-- satisfyAll = foldl andAlso mempty ---- --
-- satisfyAll = foldr andAlso mempty --satisfyAll :: Foldable t => t (ValidationRule e a) -> ValidationRule e a -- | Build a rule that succeeds if any of the given rules -- succeed. If all fail, the errors are combined. -- --
-- satisfyAny = foldl1 orElse ---- --
-- satisfyAny = foldr1 orElse ---- --
-- satisfyAny = foldl orElse falseRule ---- --
-- satisfyAny = foldr orElse falseRule --satisfyAny :: (Foldable t, Semigroup e) => t (ValidationRule e a) -> ValidationRule e a -- | A synonym for orElse. Satisfies associativity law and hence -- forms a semigroup. (>) :: Semigroup e => ValidationRule e a -> ValidationRule e a -> ValidationRule e a infixr 5 > -- | Build an any rule. -- --
-- atleastContains x = failureUnless (any x) --atleastContains :: Foldable t => (a -> Bool) -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a minimum length (inclusive) rule. -- --
-- lengthAbove x = minLengthOf (x + 1) ---- --
-- lengthAbove x = failureUnless ((>n) . length) --lengthAbove :: Foldable t => Int -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a maximum length (inclusive) rule. -- --
-- lengthBelow x = maxLengthOf (x - 1) ---- --
-- lengthBelow x = failureUnless ((<n) . length) --lengthBelow :: Foldable t => Int -> e -> ValidationRule (NonEmpty e) (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 -> ValidationRule (NonEmpty e) (t a) -- | Build a maximum length (inclusive) rule. -- --
-- maxLengthOf n = failureUnless ((<=n) . length) --maxLengthOf :: Foldable t => Int -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a maximum value (inclusive) rule. -- --
-- maxValueOf x = failureUnless (<=x) --maxValueOf :: Ord a => a -> e -> ValidationRule (NonEmpty e) a -- | Build a minimum length (inclusive) rule. -- --
-- minLengthOf x = failureUnless ((>=n) . length) --minLengthOf :: Foldable t => Int -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a minimum value (inclusive) rule. -- --
-- minValueOf x = failureUnless (>=x) --minValueOf :: Ord a => a -> e -> ValidationRule (NonEmpty e) a -- | Build an equality rule for value. -- --
-- mustBe x = failureUnless (==x) --mustBe :: Eq a => a -> e -> ValidationRule (NonEmpty e) a -- | Build an elem rule. -- --
-- mustContain x = atleastContains (==x) ---- --
-- mustContain x = failureUnless (elem x) --mustContain :: (Foldable t, Eq a) => a -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a maximum length rule. -- --
-- notEmpty = minLengthOf 1 ---- --
-- notEmpty = failureIf null --notEmpty :: Foldable t => e -> ValidationRule (NonEmpty e) (t a) -- | Build an equality rule for length. -- --
-- ofLength x = failureUnless ((==x) . length) --ofLength :: Foldable t => Int -> e -> ValidationRule (NonEmpty e) (t a) -- | Build an all rule. -- --
-- onlyContains x = failureUnless (all x) --onlyContains :: Foldable t => (a -> Bool) -> e -> ValidationRule (NonEmpty e) (t a) -- | Build a minimum value (exclusive) rule. -- --
-- valueAbove x = minValueOf (x + 1) ---- --
-- valueAbove x = failureUnless (>x) --valueAbove :: Ord a => a -> e -> ValidationRule (NonEmpty e) a -- | Build a maximum value (exclusive) rule. -- --
-- valueBelow x = minValueOf (x - 1) ---- --
-- valueBelow x = failureUnless (<x) --valueBelow :: Ord a => a -> e -> ValidationRule (NonEmpty e) 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 -> ValidationRule (NonEmpty e) a -- | Like atleastContains but uses Unit as the -- ValidationRule error type. atleastContains' :: Foldable t => (a -> Bool) -> ValidationRule () (t a) -- | Like lengthAbove but uses Unit as the -- ValidationRule error type. lengthAbove' :: Foldable t => Int -> ValidationRule () (t a) -- | Like lengthBelow but uses Unit as the -- ValidationRule error type. lengthBelow' :: Foldable t => Int -> ValidationRule () (t a) -- | Like lengthWithin but uses Unit as the -- ValidationRule error type. lengthWithin' :: Foldable t => (Int, Int) -> ValidationRule () (t a) -- | Like maxLengthOf but uses Unit as the -- ValidationRule error type. maxLengthOf' :: Foldable t => Int -> ValidationRule () (t a) -- | Like maxValueOf but uses Unit as the -- ValidationRule error type. maxValueOf' :: Ord a => a -> ValidationRule () a -- | Like minLengthOf but uses Unit as the -- ValidationRule error type. minLengthOf' :: Foldable t => Int -> ValidationRule () (t a) -- | Like minValueOf but uses Unit as the -- ValidationRule error type. minValueOf' :: Ord a => a -> ValidationRule () a -- | Like mustBe but uses Unit as the ValidationRule -- error type. mustBe' :: Eq a => a -> ValidationRule () a -- | Like mustContain but uses Unit as the -- ValidationRule error type. mustContain' :: (Foldable t, Eq a) => a -> ValidationRule () (t a) -- | Like notEmpty but uses Unit as the ValidationRule -- error type. notEmpty' :: Foldable t => ValidationRule () (t a) -- | Like ofLength but uses Unit as the ValidationRule -- error type. ofLength' :: Foldable t => Int -> ValidationRule () (t a) -- | Like onlyContains but uses Unit as the -- ValidationRule error type. onlyContains' :: Foldable t => (a -> Bool) -> ValidationRule () (t a) -- | Like valueAbove but uses Unit as the -- ValidationRule error type. valueAbove' :: Ord a => a -> ValidationRule () a -- | Like valueBelow but uses Unit as the -- ValidationRule error type. valueBelow' :: Ord a => a -> ValidationRule () a -- | Like valueWithin but uses Unit as the -- ValidationRule error type. valueWithin' :: Ord a => (a, a) -> ValidationRule () a -- | Build a rule that runs given rule only if input is Just. -- -- Yields Success when input is Nothing. -- --
-- >>> runValidator (validate (optionally (failureIf even "Even"))) (Just 5)
-- Success (Just 5)
--
-- >>> runValidator (validate (optionally (failureIf even "Even"))) (Just 6)
-- Failure ("Even" :| [])
--
-- >>> runValidator (validate (optionally (failureIf even "Even"))) Nothing
-- Success Nothing
--
optionally :: ValidationRule e a -> ValidationRule e (Maybe a)
-- | This module exports the primary validator building functions. It also
-- exports all of Valida.Combinators.
--
-- Refer to the hackage documentation for function reference and
-- examples. You can also find examples in the README, and also in the
-- github repo, within the examples directory.
module Valida
-- | Convenience alias for functions that "select" a record field.
type Selector a b = a -> b
-- | 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
-- | The rule a Validator uses to run validation.
--
-- Contains a function that accepts the target type and returns a
-- Validation result.
--
-- The type- ValidationRule (NonEmpty String) Int, designates a
-- rule that verifies the validity of an Int, and uses a value of
-- type NonEmpty String to represent error, in case of failure.
data ValidationRule e a
-- | An applicative validator. Validates a predicate on an input when run
-- and returns the Validation result.
data Validator e inp a
-- | Build a basic validator from a ValidationRule.
--
-- The Validator runs the rule on its input. If validation is
-- successful, the input is put into the Validation result.
--
-- -- validate rule = verify rule id --validate :: ValidationRule e a -> Validator e a a -- | Build a validator from a ValidationRule and a Selector. -- -- The Validator first runs given selector on its input to -- obtain the validation target. Then, it runs the ValidationRule -- on the target. -- -- If validation is successful, the validation target 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 :: ValidationRule e b -> Selector a b -> Validator e a b -- | Low level function to manually build a ValidationRule. You -- should use the combinators instead. -- --
-- >>> runValidator (validate (vrule (\x -> if isDigit x then Success () else Failure "NotDigit"))) 'a' -- Failure "NotDigit" -- -- >>> runValidator (validate (vrule (\x -> if isDigit x then Success () else Failure "NotDigit"))) '5' -- Success '5' --vrule :: (a -> Validation e ()) -> ValidationRule e a -- | A synonym for verify with its arguments flipped. (-?>) :: Selector a b -> ValidationRule e b -> Validator e a b infix 5 -?> -- | Relabel a ValidationRule with a different error. -- -- Many combinators, like failureIf' and failureUnless', -- simply return the given error value within NonEmpty upon -- failure. You can use label to override this return value. -- --
-- >>> let rule = label "NotEven" (failureUnless' even) -- -- >>> runValidator (validate rule) 1 -- Failure "NotEven" ---- --
-- >>> let rule = label "DefinitelyNotEven" (failureUnless even "NotEven") -- -- >>> runValidator (validate rule) 1 -- Failure "DefinitelyNotEven" --label :: e -> ValidationRule x a -> ValidationRule e a -- | Relabel a Validator with a different error. -- --
-- >>> let validator = labelV "NotEven" (validate (failureUnless' even)) -- -- >>> runValidator validator 1 -- Failure "NotEven" ---- --
-- >>> let validator = labelV "DefinitelyNotEven" (validate (failureUnless even "NotEven")) -- -- >>> runValidator validator 1 -- Failure "DefinitelyNotEven" --labelV :: e -> Validator x inp a -> Validator e inp a -- | A synonym for label with its arguments flipped. (>) :: ValidationRule x a -> e -> ValidationRule e a infix 6 > -- | A synonym for labelV with its arguments flipped. (?>) :: Validator x inp a -> e -> Validator e inp a infix 0 ?> -- | 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])