diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,14 @@
 `validation-selective` uses [PVP Versioning][1].
 The changelog is available [on GitHub][2].
 
+## 0.1.0.0 — May 5, 2020
+
+* [#41](https://github.com/kowainik/relude/issues/41):
+  Support GHC-8.10.1.
+* [#24](https://github.com/kowainik/relude/issues/24):
+  Add `validationAll`, `when*` and `maybe*` combinators into
+  `Validation.Combinators`.
+
 ## 0.0.0.0
 
 * Initially created.
diff --git a/src/Validation.hs b/src/Validation.hs
--- a/src/Validation.hs
+++ b/src/Validation.hs
@@ -82,6 +82,25 @@
          -- $either
        , validationToEither
        , eitherToValidation
+
+         -- * Combinators
+       , validateAll
+
+         -- ** When* functions
+       , whenSuccess
+       , whenFailure
+       , whenSuccess_
+       , whenFailure_
+       , whenSuccessM
+       , whenFailureM
+       , whenSuccessM_
+       , whenFailureM_
+
+         -- ** 'Maybe' conversion
+       , failureToMaybe
+       , successToMaybe
+       , maybeToFailure
+       , maybeToSuccess
        ) where
 
 import Control.Applicative (Alternative (..), Applicative (..))
@@ -97,7 +116,9 @@
 import GHC.Generics (Generic, Generic1)
 import GHC.TypeLits (ErrorMessage (..), TypeError)
 
+import Validation.Combinators
 
+
 -- $setup
 -- >>> import Control.Applicative (liftA3)
 -- >>> import Control.Selective (ifS)
@@ -250,6 +271,7 @@
     validateShortPassword password *> validatePasswordDigit password
 :}
 
+
 Let's see how it works:
 
 >>> validatePassword "abcd"
@@ -259,6 +281,17 @@
 >>> validatePassword "abcd12345"
 Success "abcd12345"
 
+The @validation@ library provides several convenient combinators, so
+you can write the password check in a shorter way:
+
+@
+validatePassword :: 'String' -> 'Validation' ('NonEmpty' FormValidationError) Password
+validatePassword = 'fmap' Password . 'validateAll'
+    [ (\`'failureIf'\`     ShortPassword)   . (< 8) . 'length'
+    , (\`'failureUnless'\` NoDigitPassword) . 'any' isDigit
+    ]
+@
+
 After we've implemented validations for all fields, we can compose
 them together to produce validation for the whole @User@. As before,
 we are going to use the 'Applicative' instance:
@@ -1108,7 +1141,7 @@
 {-# INLINE failure #-}
 
 {- | Returns a 'Failure' in case of the given predicate is 'True'.
-Returns @'Success' '()'@ otherwise.
+Returns @'Success' ()@ otherwise.
 
 >>> let shouldFail = (==) "I am a failure"
 >>> failureIf (shouldFail "I am a failure") "I told you so"
@@ -1123,7 +1156,7 @@
 {-# INLINE failureIf #-}
 
 {- | Returns a 'Failure' unless the given predicate is 'True'.
-Returns @'Success' '()'@ in case of the predicate is satisfied.
+Returns @'Success' ()@ in case of the predicate is satisfied.
 
 Similar to 'failureIf' with the reversed predicate.
 
diff --git a/src/Validation.hs-boot b/src/Validation.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Validation.hs-boot
@@ -0,0 +1,13 @@
+module Validation
+    ( Validation (..)
+    , validation
+    ) where
+
+
+data Validation e a
+    = Failure e
+    | Success a
+
+instance (Semigroup e) => Applicative (Validation e)
+
+validation :: (e -> x) -> (a -> x) -> Validation e a -> x
diff --git a/src/Validation/Combinators.hs b/src/Validation/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/src/Validation/Combinators.hs
@@ -0,0 +1,216 @@
+{- |
+Copyright:  (c) 2020 Kowainik
+SPDX-License-Identifier: MPL-2.0
+Maintainer: Kowainik <xrom.xkov@gmail.com>
+
+Helpful combinators to work with 'Validation' data type.
+-}
+
+module Validation.Combinators
+    ( validateAll
+
+      -- * When* functions
+    , whenSuccess
+    , whenFailure
+    , whenSuccess_
+    , whenFailure_
+    , whenSuccessM
+    , whenFailureM
+    , whenSuccessM_
+    , whenFailureM_
+
+      -- * 'Maybe' conversion
+    , failureToMaybe
+    , successToMaybe
+    , maybeToFailure
+    , maybeToSuccess
+
+    ) where
+
+import Data.Foldable (foldl')
+
+import {-# SOURCE #-} Validation (Validation (..), validation)
+
+
+{- | Validate all given checks in a 'Foldable'. Returns the 'Success' of the
+start element when all checks are successful.
+
+
+A basic example of usage could look like this:
+
+@
+> __let__ validatePassword = 'validateAll'
+        [ validateEmptyPassword
+        , validateShortPassword
+        ]
+
+> 'validateAll' \"VeryStrongPassword\"
+'Success' \"VeryStrongPassword\"
+
+> 'validateAll' ""
+'Failure' (EmptyPassword :| [ShortPassword])
+@
+-}
+validateAll
+    :: forall e b a f
+    .  (Foldable f, Semigroup e)
+    => f (a -> Validation e b)
+    -> a
+    -> Validation e a
+validateAll fs a = foldl' (\res f -> res <* f a) (Success a) fs
+{-# INLINE validateAll #-}
+
+{- | Applies the given action to 'Validation' if it is 'Failure' and returns the
+result. In case of 'Success' the default value is returned.
+
+>>> whenFailure "bar" (Failure 42) (\a -> "foo" <$ print a)
+42
+"foo"
+
+>>> whenFailure "bar" (Success 42) (\a -> "foo" <$ print a)
+"bar"
+-}
+whenFailure :: Applicative f => x -> Validation e a -> (e -> f x) -> f x
+whenFailure _ (Failure e) f = f e
+whenFailure a (Success _) _ = pure a
+{-# INLINE whenFailure #-}
+
+{- | Applies given action to the 'Validation' content if it is 'Failure'.
+
+Similar to 'whenFailure' but the default value is @()@.
+
+>>> whenFailure_ (Success 42) putStrLn
+>>> whenFailure_ (Failure "foo") putStrLn
+foo
+-}
+whenFailure_ :: Applicative f => Validation e a -> (e -> f ()) -> f ()
+whenFailure_ = whenFailure ()
+{-# INLINE whenFailure_ #-}
+
+{- | Monadic version of 'whenFailure'.
+Applies monadic action to the given 'Validation' in case of 'Failure'.
+Returns the resulting value, or provided default.
+
+>>> whenFailureM "bar" (pure $ Failure 42) (\a -> "foo" <$ print a)
+42
+"foo"
+
+>>> whenFailureM "bar" (pure $ Success 42) (\a -> "foo" <$ print a)
+"bar"
+-}
+whenFailureM :: Monad m => x -> m (Validation e a) -> (e -> m x) -> m x
+whenFailureM x mv f = mv >>= \v -> whenFailure x v f
+{-# INLINE whenFailureM #-}
+
+{- | Monadic version of 'whenFailure_'.
+Applies monadic action to the given 'Validation' in case of 'Failure'.
+Similar to 'whenFailureM' but the default is @()@.
+
+>>> whenFailureM_ (pure $ Success 42) putStrLn
+>>> whenFailureM_ (pure $ Failure "foo") putStrLn
+foo
+-}
+whenFailureM_ :: Monad m => m (Validation e a) -> (e -> m ()) -> m ()
+whenFailureM_ mv f = mv >>= \v -> whenFailure_ v f
+{-# INLINE whenFailureM_ #-}
+
+{- | Applies the given action to 'Validation' if it is 'Success' and returns the
+result. In case of 'Failure' the default value is returned.
+
+>>> whenSuccess "bar" (Failure "foo") (\a -> "success!" <$ print a)
+"bar"
+
+>>> whenSuccess "bar" (Success 42) (\a -> "success!" <$ print a)
+42
+"success!"
+-}
+whenSuccess :: Applicative f => x -> Validation e a -> (a -> f x) -> f x
+whenSuccess x (Failure  _) _ = pure x
+whenSuccess _ (Success a) f  = f a
+{-# INLINE whenSuccess #-}
+
+{- | Applies given action to the 'Validation' content if it is 'Success'.
+
+Similar to 'whenSuccess' but the default value is @()@.
+
+>>> whenSuccess_ (Failure "foo") print
+>>> whenSuccess_ (Success 42) print
+42
+-}
+whenSuccess_ :: Applicative f => Validation e a -> (a -> f ()) -> f ()
+whenSuccess_ = whenSuccess ()
+{-# INLINE whenSuccess_ #-}
+
+{- | Monadic version of 'whenSuccess'.
+Applies monadic action to the given 'Validation' in case of 'Success'.
+Returns the resulting value, or provided default.
+
+>>> whenSuccessM "bar" (pure $ Failure "foo") (\a -> "success!" <$ print a)
+"bar"
+
+>>> whenSuccessM "bar" (pure $ Success 42) (\a -> "success!" <$ print a)
+42
+"success!"
+-}
+whenSuccessM :: Monad m => x -> m (Validation e a) -> (a -> m x) -> m x
+whenSuccessM x mv f = mv >>= \v -> whenSuccess x v f
+{-# INLINE whenSuccessM #-}
+
+{- | Monadic version of 'whenSuccess_'.
+Applies monadic action to the given 'Validation' in case of 'Success'.
+Similar to 'whenSuccessM' but the default is @()@.
+
+>>> whenSuccessM_ (pure $ Failure "foo") print
+>>> whenSuccessM_ (pure $ Success 42) print
+42
+-}
+whenSuccessM_ :: Monad m => m (Validation e a) -> (a -> m ()) -> m ()
+whenSuccessM_ mv f = mv >>= \v -> whenSuccess_ v f
+{-# INLINE whenSuccessM_ #-}
+
+
+{- | Maps 'Failure' of 'Validation' to 'Just'.
+
+>>> failureToMaybe (Failure True)
+Just True
+>>> failureToMaybe (Success "aba")
+Nothing
+-}
+failureToMaybe :: Validation e a -> Maybe e
+failureToMaybe = validation Just (const Nothing)
+{-# INLINE failureToMaybe #-}
+
+{- | Maps 'Success' of 'Validation' to 'Just'.
+
+>>> successToMaybe (Failure True)
+Nothing
+>>> successToMaybe (Success "aba")
+Just "aba"
+-}
+successToMaybe :: Validation e a -> Maybe a
+successToMaybe = validation (const Nothing) Just
+{-# INLINE successToMaybe #-}
+
+{- | Maps 'Just' to 'Failure' In case of 'Nothing' it wraps the given default
+value into 'Success'.
+
+>>> maybeToFailure True (Just "aba")
+Failure "aba"
+>>> maybeToFailure True Nothing
+Success True
+-}
+maybeToFailure :: a -> Maybe e -> Validation e a
+maybeToFailure a = maybe (Success a) Failure
+{-# INLINE maybeToFailure #-}
+
+{- | Maps 'Just' to 'Success'. In case of 'Nothing' it wraps the given default
+value into 'Failure'
+
+>>> maybeToSuccess True (Just "aba")
+Success "aba"
+>>> maybeToSuccess True Nothing
+Failure True
+-}
+maybeToSuccess :: e -> Maybe a -> Validation e a
+maybeToSuccess e = maybe (Failure e) Success
+{-# INLINE maybeToSuccess #-}
diff --git a/test/Doctest.hs b/test/Doctest.hs
--- a/test/Doctest.hs
+++ b/test/Doctest.hs
@@ -23,4 +23,6 @@
     : "-XRecordWildCards"
     : "-XScopedTypeVariables"
     : "-XTypeApplications"
-    : [ "src/Validation.hs" ]
+    : [ "src/Validation.hs"
+      , "src/Validation/Combinators.hs"
+      ]
diff --git a/validation-selective.cabal b/validation-selective.cabal
--- a/validation-selective.cabal
+++ b/validation-selective.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                validation-selective
-version:             0.0.0.0
+version:             0.1.0.0
 synopsis:            Lighweight pure data validation based on Applicative and Selective functors
 description:
     Lighweight pure data validation based on Applicative and Selective
@@ -28,13 +28,14 @@
 tested-with:         GHC == 8.4.4
                      GHC == 8.6.5
                      GHC == 8.8.3
+                     GHC == 8.10.1
 
 source-repository head
   type:                git
   location:            https://github.com/kowainik/validation-selective.git
 
 common common-options
-  build-depends:       base >= 4.11.1.0 && < 4.14
+  build-depends:       base >= 4.11.1.0 && < 4.15
 
   ghc-options:         -Wall
                        -Wcompat
@@ -49,6 +50,8 @@
                        -Wpartial-fields
   if impl(ghc >= 8.8)
     ghc-options:       -Wmissing-deriving-strategies
+  if impl(ghc >= 8.10)
+    ghc-options:       -Wunused-packages
 
   default-language:    Haskell2010
   default-extensions:  ConstraintKinds
@@ -70,6 +73,7 @@
   import:              common-options
   hs-source-dirs:      src
   exposed-modules:     Validation
+                         Validation.Combinators
   build-depends:       deepseq ^>= 1.4.3.0
                      , selective >= 0.3 && < 0.5
 
@@ -86,7 +90,7 @@
                      , hspec ^>= 2.7.1
                      , hspec-hedgehog ^>= 0.0.1.1
                      , selective
-                     , text ^>= 1.2.4
+                     , text ^>= 1.2.3
   ghc-options:         -threaded
                        -rtsopts
                        -with-rtsopts=-N
