valida 1.0.0 → 1.1.0
raw patch · 5 files changed
+106/−77 lines, 5 files
Files
- ChangeLog.md +5/−0
- README.md +8/−3
- src/Valida/Combinators.hs +23/−4
- src/Valida/Validator.hs +5/−5
- valida.cabal +65/−65
ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for valida +## 1.1.0 (Aug 25, 2021) +* Add `withDefault` combinator. +* Make `optionally` preserve output of given validator. +* Remove redundant `fixV` usage from examples. + ## 1.0.0 (Aug 24, 2021) * Add `profunctors` dependency. * Add `Profunctor` instance for `Validator`.
README.md view
@@ -21,12 +21,14 @@ { inpName :: String , inpAge :: Int , inpEmail :: Maybe String + , inpFreeCake :: Maybe Bool } deriving (Show) data ValidInput = ValidInput { vInpName :: String , vInpAge :: Int , vInpEmail :: Maybe String + , vFreeCake :: Bool } deriving (Show) data FormErr @@ -35,6 +37,7 @@ | NoAtCharInMail | NoPeriodInMail | InvalidEmailLength + | YouMustGetFreeCake deriving (Show) -- | Validator for each field in the input form - built using 'Validator' combinators. @@ -48,19 +51,21 @@ <*> inpEmail -?> optionally (minLengthOf 5 InvalidEmailLength <> mustContain '@' NoAtCharInMail <> mustContain '.' NoPeriodInMail) + <*> inpFreeCake -?> failureUnless id YouMustGetFreeCake `withDefault` True goodInput :: InputForm -goodInput = InpForm "John Doe" 42 Nothing +goodInput = InpForm "John Doe" 42 Nothing (Just True) badInput :: InputForm -badInput = InpForm "John Doe" 17 (Just "@") +badInput = InpForm "John Doe" 17 (Just "@") Nothing main :: IO () main = do print (runValidator inpFormValidator goodInput) - -- Prints- Success (ValidInput {vInpName = "John Doe", vInpAge = 42, vInpEmail = Nothing}) + -- Prints- Success (ValidInput {vInpName = "John Doe", vInpAge = 42, vInpEmail = Nothing, vFreeCake = true}) print (runValidator inpFormValidator badInput) -- Prints- Failure (InvalidAge :| [InvalidEmailLength]) + ``` You can also find more examples [here](./examples/Main.hs).
src/Valida/Combinators.hs view
@@ -70,8 +70,9 @@ , valueAbove' , valueBelow' , valueWithin' - -- * Type specific 'Validator's + -- * Optional 'Validator's , optionally + , withDefault ) where import Data.Ix (Ix (inRange)) @@ -571,13 +572,31 @@ >>> runValidator (optionally (failureIf even "Even")) (Just 5) Success (Just 5) ->>> runValidator (optionally (failureIf even "Even"))) (Just 6) +>>> 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) -optionally (Validator v) = Validator $ \x -> maybe (Success x) (fmap (const x) . v) x +optionally :: Validator e inp a -> Validator e (Maybe inp) (Maybe a) +optionally (Validator v) = Validator $ maybe (Success Nothing) (fmap Just . v) + +{- | Build a validator that runs given validator only if input is 'Just'. Yields default value otherwise. + +Yields 'Success' when input is 'Nothing', and wrapped around the default value. + +@vald \`withDefault\` deflt = 'Data.Maybe.fromMaybe' deflt '<$>' 'optionally' vald@ + +==== __Examples__ + +>>> runValidator (failureIf even "Even" `withDefault` 0) (Just 5) +Success 5 +>>> runValidator (failureIf even "Even" `withDefault` 0) (Just 6) +Failure ("Even" :| []) +>>> runValidator (failureIf even "Even" `withDefault` 0) Nothing +Success 0 +-} +withDefault :: Validator e inp a -> a -> Validator e (Maybe inp) a +withDefault (Validator v) deflt = Validator $ maybe (Success deflt) v -- | Utility to convert a regular predicate function to a 'Validator'. __INTERNAL__ validatorFrom :: (a -> Bool) -> e -> Validator e a a
src/Valida/Validator.hs view
@@ -85,8 +85,8 @@ __Examples__ ->>> let v1 = fixV (failureIf (==2) "IsTwo") ->>> let v2 = fixV (failureIf even "IsEven") +>>> let v1 = failureIf (==2) "IsTwo" +>>> let v2 = failureIf even "IsEven" >>> runValidator (v1 <> v2) 5 Success 5 >>> runValidator (v1 <> v2) 4 @@ -119,11 +119,11 @@ __Examples__ ->>> runValidator (lmap fst (fixV $ failureIf (==2) "IsTwo")) (3, 2) +>>> runValidator (lmap fst (failureIf (==2) "IsTwo")) (3, 2) Success 3 ->>> runValidator (lmap snd (fixV $ failureIf (==2) "IsTwo")) (3, 2) +>>> runValidator (lmap snd (failureIf (==2) "IsTwo")) (3, 2) Failure ("IsTwo" :| []) ->>> runValidator (rmap (+1) (fixV $ failureIf (==2) "IsTwo")) 3 +>>> runValidator (rmap (+1) (failureIf (==2) "IsTwo")) 3 Failure ("IsTwo" :| []) -} instance Profunctor (Validator e) where
valida.cabal view
@@ -1,65 +1,65 @@-cabal-version: 1.12 - --- This file has been generated from package.yaml by hpack version 0.34.4. --- --- see: https://github.com/sol/hpack - -name: valida -version: 1.0.0 -synopsis: Simple applicative validation for product types, batteries included! -description: 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. -category: Validation, Data -homepage: https://github.com/TotallyNotChase/valida#readme -bug-reports: https://github.com/TotallyNotChase/valida/issues -author: Chase -maintainer: totallynotchase42@gmail.com -copyright: TotallyNotChase -license: MIT -license-file: LICENSE -build-type: Simple -extra-source-files: - README.md - ChangeLog.md - -source-repository head - type: git - location: https://github.com/TotallyNotChase/valida - -library - exposed-modules: - Valida - Valida.Combinators - other-modules: - Valida.Utils - Valida.Validation - Valida.ValidationUtils - Valida.Validator - Paths_valida - hs-source-dirs: - src - ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wmissed-specialisations -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -O2 - build-depends: - base >=4.12 && <5 - , profunctors >=5 - default-language: Haskell2010 - -test-suite valida-test - type: exitcode-stdio-1.0 - main-is: Spec.hs - other-modules: - Gen - Utils - Paths_valida - hs-source-dirs: - test - ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wmissed-specialisations -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N - build-depends: - base >=4.12 && <5 - , profunctors >=5 - , smallcheck >=1.2 - , tasty - , tasty-hunit - , tasty-quickcheck - , tasty-smallcheck - , valida - default-language: Haskell2010 +cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack++name: valida+version: 1.1.0+synopsis: Simple applicative validation for product types, batteries included!+description: 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.+category: Validation, Data+homepage: https://github.com/TotallyNotChase/valida#readme+bug-reports: https://github.com/TotallyNotChase/valida/issues+author: Chase+maintainer: totallynotchase42@gmail.com+copyright: TotallyNotChase+license: MIT+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md++source-repository head+ type: git+ location: https://github.com/TotallyNotChase/valida++library+ exposed-modules:+ Valida+ Valida.Combinators+ other-modules:+ Valida.Utils+ Valida.Validation+ Valida.ValidationUtils+ Valida.Validator+ Paths_valida+ hs-source-dirs:+ src+ ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wmissed-specialisations -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -O2+ build-depends:+ base >=4.12 && <5+ , profunctors >=5+ default-language: Haskell2010++test-suite valida-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Gen+ Utils+ Paths_valida+ hs-source-dirs:+ test+ ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wmissed-specialisations -Wmissing-export-lists -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.12 && <5+ , profunctors >=5+ , smallcheck >=1.2+ , tasty+ , tasty-hunit+ , tasty-quickcheck+ , tasty-smallcheck+ , valida+ default-language: Haskell2010