packages feed

validation 0.6.3 → 1

raw patch · 5 files changed

+159/−155 lines, 5 filesdep ~basedep ~hedgehog

Dependency ranges changed: base, hedgehog

Files

changelog view
@@ -1,3 +1,7 @@+1++* Rename `AccValidation` to `Validation`+ 0.6.3  * Add `Generic` and `NFData` instances
src/Data/Validation.hs view
@@ -11,7 +11,7 @@ module Data.Validation (   -- * Data type-  AccValidation(..)+  Validation(..)   -- * Constructing validations , validate , validationNel@@ -28,7 +28,7 @@ , bindValidation   -- * 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+  -- choice of Either or Validation. This choice can then be made later by a   -- user, depending on their needs.   --   -- An example of this style of usage can be found@@ -71,19 +71,19 @@ import Prelude(Show)  --- | 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@.+-- | An @Validation@ is either a value of the type @err@ or @a@, similar to 'Either'. However,+-- the 'Applicative' instance for @Validation@ /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 'Data.Functor.Bind.Bind' or 'Control.Monad.Monad' instance. This is because+-- A consequence of this is that @Validation@ has no 'Data.Functor.Bind.Bind' or 'Control.Monad.Monad' instance. This is because -- such an instance would violate the law that a Monad's 'Control.Monad.ap' must equal the -- @Applicative@'s 'Control.Applicative.<*>' -- -- An example of typical usage can be found <https://github.com/qfpl/validation/blob/master/examples/src/Email.hs here>. ---data AccValidation err a =-  AccFailure err-  | AccSuccess a+data Validation err a =+  Failure err+  | Success a   deriving (     Eq, Ord, Show, Data, Typeable #if __GLASGOW_HASKELL__ >= 702@@ -91,123 +91,123 @@ #endif   ) -instance Functor (AccValidation err) where-  fmap _ (AccFailure e) =-    AccFailure e-  fmap f (AccSuccess a) =-    AccSuccess (f a)+instance Functor (Validation err) where+  fmap _ (Failure e) =+    Failure e+  fmap f (Success a) =+    Success (f a)   {-# INLINE fmap #-} -instance Semigroup err => Apply (AccValidation err) where-  AccFailure e1 <.> b = AccFailure $ case b of-    AccFailure e2 -> e1 <> e2-    AccSuccess _ -> e1-  AccSuccess _  <.> AccFailure e2 =-    AccFailure e2-  AccSuccess f  <.> AccSuccess a  =-    AccSuccess (f a)+instance Semigroup err => Apply (Validation err) where+  Failure e1 <.> b = Failure $ case b of+    Failure e2 -> e1 <> e2+    Success _ -> e1+  Success _  <.> Failure e2 =+    Failure e2+  Success f  <.> Success a  =+    Success (f a)   {-# INLINE (<.>) #-} -instance Semigroup err => Applicative (AccValidation err) where+instance Semigroup err => Applicative (Validation err) where   pure =-    AccSuccess+    Success   (<*>) =     (<.>) -instance Alt (AccValidation err) where-  AccFailure _ <!> x =+instance Alt (Validation err) where+  Failure _ <!> x =     x-  AccSuccess a <!> _ =-    AccSuccess a+  Success a <!> _ =+    Success a   {-# INLINE (<!>) #-} -instance Foldable (AccValidation err) where-  foldr f x (AccSuccess a) =+instance Foldable (Validation err) where+  foldr f x (Success a) =     f a x-  foldr _ x (AccFailure _) =+  foldr _ x (Failure _) =     x   {-# INLINE foldr #-} -instance Traversable (AccValidation err) where-  traverse f (AccSuccess a) =-    AccSuccess <$> f a-  traverse _ (AccFailure e) =-    pure (AccFailure e)+instance Traversable (Validation err) where+  traverse f (Success a) =+    Success <$> f a+  traverse _ (Failure e) =+    pure (Failure e)   {-# INLINE traverse #-} -instance Bifunctor AccValidation where-  bimap f _ (AccFailure e) =-    AccFailure (f e)-  bimap _ g (AccSuccess a) =-    AccSuccess (g a)+instance Bifunctor Validation where+  bimap f _ (Failure e) =+    Failure (f e)+  bimap _ g (Success a) =+    Success (g a)   {-# INLINE bimap #-}  -instance Bifoldable AccValidation where-  bifoldr _ g x (AccSuccess a) =+instance Bifoldable Validation where+  bifoldr _ g x (Success a) =     g a x-  bifoldr f _ x (AccFailure e) =+  bifoldr f _ x (Failure e) =     f e x   {-# INLINE bifoldr #-} -instance Bitraversable AccValidation where-  bitraverse _ g (AccSuccess a) =-    AccSuccess <$> g a-  bitraverse f _ (AccFailure e) =-    AccFailure <$> f e+instance Bitraversable Validation where+  bitraverse _ g (Success a) =+    Success <$> g a+  bitraverse f _ (Failure e) =+    Failure <$> f e   {-# INLINE bitraverse #-} -appAccValidation ::+appValidation ::   (err -> err -> err)-  -> AccValidation err a-  -> AccValidation err a-  -> AccValidation err a-appAccValidation m (AccFailure e1) (AccFailure e2) =-  AccFailure (e1 `m` e2)-appAccValidation _ (AccFailure _) (AccSuccess a2) =-  AccSuccess a2-appAccValidation _ (AccSuccess a1) (AccFailure _) =-  AccSuccess a1-appAccValidation _ (AccSuccess a1) (AccSuccess _) =-  AccSuccess a1-{-# INLINE appAccValidation #-}+  -> Validation err a+  -> Validation err a+  -> Validation err a+appValidation m (Failure e1) (Failure e2) =+  Failure (e1 `m` e2)+appValidation _ (Failure _) (Success a2) =+  Success a2+appValidation _ (Success a1) (Failure _) =+  Success a1+appValidation _ (Success a1) (Success _) =+  Success a1+{-# INLINE appValidation #-} -instance Semigroup e => Semigroup (AccValidation e a) where+instance Semigroup e => Semigroup (Validation e a) where   (<>) =-    appAccValidation (<>)+    appValidation (<>)   {-# INLINE (<>) #-} -instance Monoid e => Monoid (AccValidation e a) where+instance Monoid e => Monoid (Validation e a) where   mappend =-    appAccValidation mappend+    appValidation mappend   {-# INLINE mappend #-}   mempty =-    AccFailure mempty+    Failure mempty   {-# INLINE mempty #-} -instance Swapped AccValidation where+instance Swapped Validation where   swapped =     iso       (\v -> case v of-        AccFailure e -> AccSuccess e-        AccSuccess a -> AccFailure a)+        Failure e -> Success e+        Success a -> Failure a)       (\v -> case v of-        AccFailure a -> AccSuccess a-        AccSuccess e -> AccFailure e)+        Failure a -> Success a+        Success e -> Failure e)   {-# INLINE swapped #-} -instance (NFData e, NFData a) => NFData (AccValidation e a) where+instance (NFData e, NFData a) => NFData (Validation e a) where   rnf v =     case v of-      AccFailure e -> rnf e-      AccSuccess a -> rnf a+      Failure e -> rnf e+      Success a -> rnf a  -- | '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+-- validate :: e -> (a -> Bool) -> a -> Validation e a -- @ validate :: Validate v => e -> (a -> Bool) -> a -> v e a validate e p a =@@ -215,54 +215,54 @@  -- | 'validationNel' is 'liftError' specialised to 'NonEmpty' lists, since -- they are a common semigroup to use.-validationNel :: Either e a -> AccValidation (NonEmpty e) a+validationNel :: Either e a -> Validation (NonEmpty e) a validationNel = liftError pure --- | Converts from 'Either' to 'AccValidation'.-fromEither :: Either e a -> AccValidation e a+-- | Converts from 'Either' to 'Validation'.+fromEither :: Either e a -> Validation e a fromEither = liftError id --- | 'liftError' is useful for converting an 'Either' to an 'AccValidation'+-- | 'liftError' is useful for converting an 'Either' to an 'Validation' -- when the @Left@ of the 'Either' needs to be lifted into a 'Semigroup'.-liftError :: (b -> e) -> Either b a -> AccValidation e a-liftError f = either (AccFailure . f) AccSuccess+liftError :: (b -> e) -> Either b a -> Validation e a+liftError f = either (Failure . f) Success --- | 'validation' is the catamorphism for @AccValidation@.-validation :: (e -> c) -> (a -> c) -> AccValidation e a -> c+-- | 'validation' is the catamorphism for @Validation@.+validation :: (e -> c) -> (a -> c) -> Validation e a -> c validation ec ac v = case v of-  AccFailure e -> ec e-  AccSuccess a -> ac a+  Failure e -> ec e+  Success a -> ac a --- | Converts from 'AccValidation' to 'Either'.-toEither :: AccValidation e a -> Either e a+-- | Converts from 'Validation' to 'Either'.+toEither :: Validation e a -> Either e a toEither = validation Left Right --- | @v 'orElse' a@ returns @a@ when @v@ is AccFailure, and the @a@ in @AccSuccess a@.+-- | @v 'orElse' a@ returns @a@ when @v@ is Failure, and the @a@ in @Success a@. -- -- This can be thought of as having the less general type: -- -- @--- orElse :: AccValidation e a -> a -> a+-- orElse :: Validation e a -> a -> a -- @ orElse :: Validate v => v e a -> a -> a-orElse v a = case v ^. _AccValidation of-  AccFailure _ -> a-  AccSuccess x -> x+orElse v a = case v ^. _Validation of+  Failure _ -> a+  Success x -> x  -- | 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+-- valueOr :: (e -> a) -> Validation e a -> a -- @ valueOr :: Validate v => (e -> a) -> v e a -> a-valueOr ea v = case v ^. _AccValidation of-  AccFailure e -> ea e-  AccSuccess a -> a+valueOr ea v = case v ^. _Validation of+  Failure e -> ea e+  Success a -> a  -- | 'codiagonal' gets the value out of either side.-codiagonal :: AccValidation a a -> a+codiagonal :: Validation a a -> a codiagonal = valueOr id  -- | 'ensure' leaves the validation unchanged when the predicate holds, or@@ -271,79 +271,79 @@ -- This can be thought of as having the less general type: -- -- @--- ensure :: e -> (a -> Bool) -> AccValidation e a -> AccValidation e a+-- ensure :: e -> (a -> Bool) -> Validation e a -> Validation e a -- @ ensure :: Validate v => e -> (a -> Bool) -> v e a -> v e a ensure e p =-  over _AccValidation $ \v -> case v of-    AccFailure x -> AccFailure x-    AccSuccess a -> validate e p a+  over _Validation $ \v -> case v of+    Failure x -> Failure x+    Success a -> validate e p a  -- | Run a function on anything with a Validate instance (usually Either)--- as if it were a function on AccValidation+-- as if it were a function on Validation -- -- This can be thought of as having the type ----- @(Either e a -> Either e' a') -> AccValidation e a -> AccValidation e' a'@-validationed :: Validate v => (v e a -> v e' a') -> AccValidation e a -> AccValidation e' a'-validationed f = under _AccValidation f+-- @(Either e a -> Either e' a') -> Validation e a -> Validation e' a'@+validationed :: Validate v => (v e a -> v e' a') -> Validation e a -> Validation e' a'+validationed f = under _Validation f --- | @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.+-- | @bindValidation@ binds through an Validation, which is useful for+-- composing Validations sequentially. Note that despite having a bind+-- function of the correct type, Validation 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.-bindValidation :: AccValidation e a -> (a -> AccValidation e b) -> AccValidation e b+bindValidation :: Validation e a -> (a -> Validation e b) -> Validation e b bindValidation v f = case v of-  AccFailure e -> AccFailure e-  AccSuccess a -> f a+  Failure e -> Failure e+  Success a -> f a  -- | The @Validate@ class carries around witnesses that the type @f@ is isomorphic--- to AccValidation, and hence isomorphic to Either.+-- to Validation, and hence isomorphic to Either. class Validate f where-  _AccValidation ::-    Iso (f e a) (f g b) (AccValidation e a) (AccValidation g b)+  _Validation ::+    Iso (f e a) (f g b) (Validation e a) (Validation g b)    _Either ::     Iso (f e a) (f g b) (Either e a) (Either g b)   _Either =     iso-      (\x -> case x ^. _AccValidation of-        AccFailure e -> Left e-        AccSuccess a -> Right a)-      (\x -> _AccValidation # case x of-        Left e -> AccFailure e-        Right a -> AccSuccess a)+      (\x -> case x ^. _Validation of+        Failure e -> Left e+        Success a -> Right a)+      (\x -> _Validation # case x of+        Left e -> Failure e+        Right a -> Success a)   {-# INLINE _Either #-} -instance Validate AccValidation where-  _AccValidation =+instance Validate Validation where+  _Validation =     id-  {-# INLINE _AccValidation #-}+  {-# INLINE _Validation #-}   _Either =     iso       (\x -> case x of-        AccFailure e -> Left e-        AccSuccess a -> Right a)+        Failure e -> Left e+        Success a -> Right a)       (\x -> case x of-        Left e -> AccFailure e-        Right a -> AccSuccess a)+        Left e -> Failure e+        Right a -> Success a)   {-# INLINE _Either #-}  instance Validate Either where-  _AccValidation =+  _Validation =     iso       fromEither       toEither-  {-# INLINE _AccValidation #-}+  {-# INLINE _Validation #-}   _Either =     id   {-# INLINE _Either #-} --- | This prism generalises 'Control.Lens.Prism._Left'. It targets the failure case of either 'Either' or 'AccValidation'.+-- | This prism generalises 'Control.Lens.Prism._Left'. It targets the failure case of either 'Either' or 'Validation'. _Failure ::   Validate f =>   Prism (f e1 a) (f e2 a) e1 e2@@ -355,7 +355,7 @@              Right a -> Left (_Either # Right a)) {-# INLINE _Failure #-} --- | This prism generalises 'Control.Lens.Prism._Right'. It targets the success case of either 'Either' or 'AccValidation'.+-- | This prism generalises 'Control.Lens.Prism._Right'. It targets the success case of either 'Either' or 'Validation'. _Success ::   Validate f =>   Prism (f e a) (f e b) a b@@ -369,5 +369,5 @@  -- | 'revalidate' converts between any two instances of 'Validate'. revalidate :: (Validate f, Validate g) => Iso (f e1 s) (f e2 t) (g e1 s) (g e2 t)-revalidate = _AccValidation . from _AccValidation+revalidate = _Validation . from _Validation 
test/hedgehog_tests.hs view
@@ -9,7 +9,7 @@ import System.IO (BufferMode(..), hSetBuffering, stdout, stderr) import System.Exit (exitFailure) -import Data.Validation (AccValidation (AccSuccess, AccFailure))+import Data.Validation (Validation (Success, Failure))  main :: IO () main = do@@ -26,17 +26,17 @@   unless result $     exitFailure -genAccValidation :: Gen e -> Gen a -> Gen (AccValidation e a)-genAccValidation e a = Gen.choice [fmap AccFailure e, fmap AccSuccess a]+genValidation :: Gen e -> Gen a -> Gen (Validation e a)+genValidation e a = Gen.choice [fmap Failure e, fmap Success a] -testGen :: Gen (AccValidation [String] Int)+testGen :: Gen (Validation [String] Int) testGen =   let range = Range.linear 1 50       string = Gen.string range Gen.unicode       strings = Gen.list range string-  in  genAccValidation strings Gen.enumBounded+  in  genValidation strings Gen.enumBounded -mkAssoc :: (AccValidation [String] Int -> AccValidation [String] Int -> AccValidation [String] Int) -> Property+mkAssoc :: (Validation [String] Int -> Validation [String] Int -> Validation [String] Int) -> Property mkAssoc f =   let g = forAll testGen       assoc = \x y z -> ((x `f` y) `f` z) === (x `f` (y `f` z))
test/hunit_tests.hs view
@@ -9,7 +9,7 @@ import Control.Monad (when) import Data.Foldable (length) import Data.Proxy (Proxy (Proxy))-import Data.Validation (AccValidation (AccSuccess, AccFailure), Validate, _Failure, _Success, ensure,+import Data.Validation (Validation (Success, Failure), Validate, _Failure, _Success, ensure,                         orElse, validate, validation, validationNel) import System.Exit (exitFailure) @@ -21,26 +21,26 @@  testYY :: Test testYY =-  let subject  = _Success # (+1) <*> _Success # seven :: AccValidation String Int-      expected = AccSuccess 8+  let subject  = _Success # (+1) <*> _Success # seven :: Validation String Int+      expected = Success 8   in  TestCase (assertEqual "Success <*> Success" subject expected)  testNY :: Test testNY =-  let subject  = _Failure # ["f1"] <*> _Success # seven :: AccValidation [String] Int-      expected = AccFailure ["f1"]+  let subject  = _Failure # ["f1"] <*> _Success # seven :: Validation [String] Int+      expected = Failure ["f1"]   in  TestCase (assertEqual "Failure <*> Success" subject expected)  testYN :: Test testYN =-  let subject  = _Success # (+1) <*> _Failure # ["f2"] :: AccValidation [String] Int-      expected = AccFailure ["f2"]+  let subject  = _Success # (+1) <*> _Failure # ["f2"] :: Validation [String] Int+      expected = Failure ["f2"]   in  TestCase (assertEqual "Success <*> Failure" subject expected)  testNN :: Test testNN =-  let subject  = _Failure # ["f1"] <*> _Failure # ["f2"] :: AccValidation [String] Int-      expected = AccFailure ["f1","f2"]+  let subject  = _Failure # ["f1"] <*> _Failure # ["f2"] :: Validation [String] Int+      expected = Failure ["f1","f2"]   in  TestCase (assertEqual "Failure <*> Failure" subject expected)  testValidationNel :: Test@@ -87,20 +87,20 @@ testValidateTrue :: Test testValidateTrue =   let subject = validate three (const True) seven-      expected = AccSuccess seven+      expected = Success seven   in  TestCase (assertEqual "testValidateTrue" subject expected)  testValidateFalse :: Test testValidateFalse =   let subject = validate three (const False) seven-      expected = AccFailure three+      expected = Failure three   in  TestCase (assertEqual "testValidateFalse" subject expected)  tests :: Test tests =   let eitherP :: Proxy Either       eitherP = Proxy-      validationP :: Proxy AccValidation+      validationP :: Proxy Validation       validationP = Proxy       generals :: forall v. (Validate v, Eq (v Int Int), Show (v Int Int)) => [Proxy v -> Test]       generals =
validation.cabal view
@@ -1,5 +1,5 @@ name:               validation-version:            0.6.3+version:            1 license:            BSD3 license-file:       LICENCE author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> <dibblego>, Nick Partridge <nkpart>@@ -19,15 +19,15 @@   `lens`-related functions for converting between each and abstracting over their   similarities.   .-  * `AccValidation`+  * `Validation`   .-  The `AccValidation` data type is isomorphic to `Either`, but has an instance+  The `Validation` data type is isomorphic to `Either`, but has an instance   of `Applicative` that accumulates on the error side. That is to say, if two   (or more) errors are encountered, they are appended using a `Semigroup`   operation.   .   As a consequence of this `Applicative` instance, there is no corresponding-  `Bind` or `Monad` instance. `AccValidation` is an example of, "An applicative+  `Bind` or `Monad` instance. `Validation` is an example of, "An applicative   functor that is not a monad."  homepage:           https://github.com/qfpl/validation@@ -46,7 +46,7 @@                     Haskell2010    build-depends:-                      base          >= 3   && < 5+                      base          >= 4.5 && < 5                     , deepseq       >= 1.2 && < 1.5                     , semigroups    >= 0.8 && < 1                     , semigroupoids >= 5   && < 6