diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,15 @@
+1.3.2
+
+* Change the Extend instances for all four validators to keep failures,
+  like Validation: for each input, extended fails where the validator
+  fails, rather than always succeeding. The constraint on the monadic
+  validators is relaxed to Functor
+* Generalise the ReviewValidation instance for ValidationMonad to
+  ValidationMonadT over any Applicative
+* Relax constraints: Choice for ValidatorProfunctor no longer requires
+  Semigroup, Sieve for ValidatorMonadProfunctorT requires only Functor,
+  and the MonadFail instances no longer require a redundant Monad
+
 1.3.1
 
 * Change the Alt instance for Validator to be like Either: the first
diff --git a/src/Data/Validation/Validation.hs b/src/Data/Validation/Validation.hs
--- a/src/Data/Validation/Validation.hs
+++ b/src/Data/Validation/Validation.hs
@@ -9,20 +9,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# OPTIONS_GHC -Wall #-}
 
--- \$setup
--- >>> import Prelude hiding (either, id, (.))
--- >>> import Control.Lens((^?), (#), review, view, from, set)
--- >>> import Data.Functor.Alt(Alt((<!>)))
--- >>> import Data.Functor.Apply(Apply((<.>)))
--- >>> import Control.DeepSeq(rnf)
--- >>> import Control.Category(id, (.))
--- >>> import Control.Selective(Selective(select))
--- >>> import Data.Bifunctor(Bifunctor(bimap))
--- >>> import Data.Bifoldable(Bifoldable(bifoldr))
--- >>> import Data.Bitraversable(Bitraversable(bitraverse))
--- >>> import Data.Bifunctor.Swap(Swap(swap))
--- >>> :set -XNoMonomorphismRestriction -w
-
 -- | A data type similar to @Data.Either@ that accumulates failures.
 module Data.Validation.Validation (
   -- * Data type
@@ -74,6 +60,21 @@
 import Data.Typeable (Typeable)
 import GHC.Generics (Generic, Generic1)
 import Prelude hiding (either, id, (.))
+
+{- $setup
+>>> import Prelude hiding (either, id, (.))
+>>> import Control.Lens((^?), (#), review, view, from, set)
+>>> import Data.Functor.Alt(Alt((<!>)))
+>>> import Data.Functor.Apply(Apply((<.>)))
+>>> import Control.DeepSeq(rnf)
+>>> import Control.Category(id, (.))
+>>> import Control.Selective(Selective(select))
+>>> import Data.Bifunctor(Bifunctor(bimap))
+>>> import Data.Bifoldable(Bifoldable(bifoldr))
+>>> import Data.Bitraversable(Bitraversable(bitraverse))
+>>> import Data.Bifunctor.Swap(Swap(swap))
+>>> :set -XNoMonomorphismRestriction -w
+-}
 
 {- | A @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@.
diff --git a/src/Data/Validation/ValidationMonad.hs b/src/Data/Validation/ValidationMonad.hs
--- a/src/Data/Validation/ValidationMonad.hs
+++ b/src/Data/Validation/ValidationMonad.hs
@@ -9,21 +9,6 @@
 {-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -Wall #-}
 
--- \$setup
--- >>> import Data.Functor.Identity(Identity(..))
--- >>> import Data.Validation.Validation(Validation(..))
--- >>> import Data.Validation.ValidationMonad
--- >>> import Control.Lens(view, _Wrapped', review, (#), (^?), from)
--- >>> import Data.Functor.Alt(Alt((<!>)))
--- >>> import Data.Functor.Apply(Apply((<.>)))
--- >>> import Data.Functor.Extend(Extend(extended))
--- >>> import Data.Functor.Classes(Eq1(liftEq), Ord1(liftCompare))
--- >>> import Control.Monad.Error.Class(MonadError(throwError, catchError))
--- >>> import Control.Monad.Trans.Class(MonadTrans(lift))
--- >>> import Control.DeepSeq(rnf)
--- >>> import Data.Functor.Plus(Plus(zero))
--- >>> :set -XNoMonomorphismRestriction -w
-
 {- | A monad transformer wrapping @m (Validation err a)@ with short-circuiting
 'Applicative' and 'Monad' instances, unlike 'Validation' which accumulates errors.
 -}
@@ -48,8 +33,8 @@
 
 import Control.Applicative (Alternative (empty, (<|>)))
 import Control.DeepSeq (NFData (rnf))
-import Control.Lens (Getter, Lens', Prism', Review, Rewrapped, Wrapped (_Wrapped', type Unwrapped), from, prism', unto)
-import Control.Lens.Iso (Iso, iso)
+import Control.Lens (Getter, Lens', Prism', Review, Rewrapped, Wrapped (_Wrapped', type Unwrapped), from, unto)
+import Control.Lens.Iso (Iso, Iso', iso)
 import Control.Monad (MonadPlus, ap)
 import Control.Monad.Cont.Class (MonadCont (callCC))
 import Control.Monad.Error.Class (MonadError (catchError, throwError))
@@ -60,7 +45,6 @@
 import Control.Monad.Trans.Class (MonadTrans (lift))
 import Control.Monad.Writer.Class (MonadWriter (listen, pass, tell, writer))
 import Control.Selective (Selective (select), selectM)
-import qualified Data.Either as Either
 import Data.Functor.Alt (Alt ((<!>)))
 import Data.Functor.Apply (Apply ((<.>)))
 import Data.Functor.Bind (Bind ((>>-)))
@@ -70,8 +54,25 @@
 import Data.Functor.Identity (Identity (..))
 import Data.Functor.Plus (Plus (zero))
 import Data.Validation.Validation (AsValidation (..), GetValidation (..), HasValidation (..), ReviewValidation (..), Validation (..), foldValidation)
+import qualified Data.Validation.Validation as Validation
 import GHC.Generics (Generic)
 
+{- $setup
+>>> import Data.Functor.Identity(Identity(..))
+>>> import Data.Validation.Validation(Validation(..))
+>>> import Data.Validation.ValidationMonad
+>>> import Control.Lens(view, _Wrapped', review, (#), (^?), from)
+>>> import Data.Functor.Alt(Alt((<!>)))
+>>> import Data.Functor.Apply(Apply((<.>)))
+>>> import Data.Functor.Extend(Extend(extended))
+>>> import Data.Functor.Classes(Eq1(liftEq), Ord1(liftCompare))
+>>> import Control.Monad.Error.Class(MonadError(throwError, catchError))
+>>> import Control.Monad.Trans.Class(MonadTrans(lift))
+>>> import Control.DeepSeq(rnf)
+>>> import Data.Functor.Plus(Plus(zero))
+>>> :set -XNoMonomorphismRestriction -w
+-}
+
 {- | A monad transformer wrapping @m (Validation err a)@.
 
 >>> ValidationMonadT (Identity (Success 1)) :: ValidationMonadT String Identity Int
@@ -214,7 +215,7 @@
       Success a -> let ValidationMonadT n = k a in n
   {-# INLINE (>>=) #-}
 
-instance (Monad m, MonadFail m) => MonadFail (ValidationMonadT err m) where
+instance (MonadFail m) => MonadFail (ValidationMonadT err m) where
   fail = liftValidationMonadT . fail
   {-# INLINE fail #-}
 
@@ -425,7 +426,7 @@
   reviewValidationMonadT :: Review s (ValidationMonadT err m a)
 
 instance ReviewValidationMonadT (ValidationMonadT err m a) err m a where
-  reviewValidationMonadT = unto id
+  reviewValidationMonadT = id
   {-# INLINE reviewValidationMonadT #-}
 
 -- | Class for types that have a 'Prism'' to a 'ValidationMonadT'.
@@ -449,6 +450,11 @@
 validationMonad = iso (ValidationMonadT . pure) (\(ValidationMonadT (Identity v)) -> v)
 {-# INLINE validationMonad #-}
 
+-- Isomorphism between @Either err a@ and @ValidationMonad err a@.
+eitherValidationMonad :: Iso' (Either err a) (ValidationMonad err a)
+eitherValidationMonad = from Validation.either . validationMonad
+{-# INLINE eitherValidationMonad #-}
+
 {- |
 >>> import Control.Lens(view)
 >>> view getValidationMonadT (Success 1 :: Validation String Int)
@@ -473,7 +479,7 @@
 Success 1
 -}
 instance ReviewValidationMonadT (Validation err a) err Identity a where
-  reviewValidationMonadT = unto (\(ValidationMonadT (Identity v)) -> v)
+  reviewValidationMonadT = validationMonad
   {-# INLINE reviewValidationMonadT #-}
 
 {- |
@@ -482,10 +488,7 @@
 Just (ValidationMonadT (Identity (Success 1)))
 -}
 instance AsValidationMonadT (Validation err a) err Identity a where
-  _ValidationMonadT =
-    prism'
-      (\(ValidationMonadT (Identity v)) -> v)
-      (Just . ValidationMonadT . pure)
+  _ValidationMonadT = validationMonad
   {-# INLINE _ValidationMonadT #-}
 
 {- |
@@ -506,8 +509,13 @@
   validation = from validationMonad
   {-# INLINE validation #-}
 
-instance ReviewValidation (ValidationMonad err a) err a where
-  reviewValidation = unto (ValidationMonadT . Identity)
+{- |
+>>> import Control.Lens(review)
+>>> review reviewValidation (Success 1 :: Validation String Int) :: ValidationMonadT String [] Int
+ValidationMonadT [Success 1]
+-}
+instance (Applicative m) => ReviewValidation (ValidationMonadT err m a) err a where
+  reviewValidation = unto (ValidationMonadT . pure)
   {-# INLINE reviewValidation #-}
 
 {- |
@@ -528,7 +536,7 @@
 ValidationMonadT (Identity (Success 1))
 -}
 instance GetValidationMonadT (Either err a) err Identity a where
-  getValidationMonadT = iso (ValidationMonadT . Identity . Either.either Failure Success) (\(ValidationMonadT (Identity v)) -> foldValidation Left Right v)
+  getValidationMonadT = eitherValidationMonad
   {-# INLINE getValidationMonadT #-}
 
 {- |
@@ -540,7 +548,7 @@
 Right 2
 -}
 instance HasValidationMonadT (Either err a) err Identity a where
-  validationMonadT = iso (ValidationMonadT . Identity . Either.either Failure Success) (\(ValidationMonadT (Identity v)) -> foldValidation Left Right v)
+  validationMonadT = eitherValidationMonad
   {-# INLINE validationMonadT #-}
 
 {- |
@@ -552,7 +560,7 @@
 Left "err"
 -}
 instance ReviewValidationMonadT (Either err a) err Identity a where
-  reviewValidationMonadT = unto (\(ValidationMonadT (Identity v)) -> foldValidation Left Right v)
+  reviewValidationMonadT = eitherValidationMonad
   {-# INLINE reviewValidationMonadT #-}
 
 {- |
@@ -564,5 +572,5 @@
 Just (ValidationMonadT (Identity (Success 1)))
 -}
 instance AsValidationMonadT (Either err a) err Identity a where
-  _ValidationMonadT = iso (ValidationMonadT . Identity . Either.either Failure Success) (\(ValidationMonadT (Identity v)) -> foldValidation Left Right v)
+  _ValidationMonadT = eitherValidationMonad
   {-# INLINE _ValidationMonadT #-}
diff --git a/src/Data/Validation/Validator.hs b/src/Data/Validation/Validator.hs
--- a/src/Data/Validation/Validator.hs
+++ b/src/Data/Validation/Validator.hs
@@ -75,8 +75,8 @@
 import Control.Applicative (Alternative (empty, (<|>)))
 import Control.Arrow (Arrow (arr, first), ArrowApply (app), ArrowChoice (left, right), ArrowPlus ((<+>)), ArrowZero (zeroArrow))
 import Control.Category (Category (..))
-import Control.Lens (APrism, Getter, Lens', Prism', Review, Rewrapped, Wrapped (_Wrapped', type Unwrapped), matching, review, unto)
-import Control.Lens.Iso (iso)
+import Control.Lens (APrism, Getter, Lens', Prism', Review, Rewrapped, Wrapped (_Wrapped', type Unwrapped), from, matching, review, unto, view)
+import Control.Lens.Iso (Iso', iso)
 import Control.Monad (MonadPlus, ap, (>=>))
 import Control.Monad.Cont.Class (MonadCont (callCC))
 import Control.Monad.Error.Class (MonadError (catchError, throwError))
@@ -102,7 +102,7 @@
 import Data.Semigroupoid (Semigroupoid (o))
 import Data.Validation.Validation (Validation (..))
 import qualified Data.Validation.Validation as Validation
-import Data.Validation.ValidationMonad (ValidationMonadT (..), liftValidationMonadT)
+import Data.Validation.ValidationMonad (ValidationMonadT (..), liftValidationMonadT, validationMonad)
 import GHC.Generics (Generic)
 import Prelude hiding (id, (.))
 
@@ -151,6 +151,11 @@
 {- | A validator that applies a function @x -> Validation err a@.
 The 'Applicative' instance /accumulates/ errors using 'Semigroup', like 'Validation'.
 
+Unlike 'Validation' and the other validators, the 'Alt' instance does /not/
+accumulate errors: it behaves like 'Either', returning the first success, or
+otherwise the second failure. As a consequence there are no 'Plus' or
+'Alternative' instances, and '<>' (which accumulates) differs from '<!>'.
+
 >>> let Validator f = Validator (\x -> if x > 0 then Success x else Failure ["not positive"]) :: Validator Int [String] Int
 >>> f 5
 Success 5
@@ -221,6 +226,12 @@
 {- | First success wins, like 'Either'; if both fail, the second failure is returned.
 Errors are not accumulated, so no 'Semigroup' constraint is required.
 
+This differs from the 'Alt' instances for 'Validation', 'ValidatorProfunctor',
+'ValidatorMonadT' and 'ValidatorMonadProfunctorT', which all accumulate errors
+when both sides fail. Converting a 'Validator' to one of those types (for
+example with 'validatorProfunctor') therefore changes the meaning of '<!>'.
+Use '<>' to accumulate errors from two 'Validator's.
+
 >>> import Data.Functor.Alt(Alt((<!>)))
 >>> let Validator f = (Validator (\_ -> Success 1) :: Validator Int [String] Int) <!> Validator (\_ -> Success 2)
 >>> f 0
@@ -293,17 +304,28 @@
   swap (Validator f) = Validator (swap . f)
   {-# INLINE swap #-}
 
-{- |
+{- | Like 'Validation', a failure is kept: for each input, the result fails
+where the validator fails, and otherwise succeeds with @f@ applied to the validator.
+
 >>> import Data.Functor.Extend(Extend(extended))
 >>> let Validator f = extended (\_ -> 42) (Validator (\_ -> Success 1) :: Validator Int [String] Int)
 >>> f 0
 Success 42
+
+>>> let Validator f = extended (\_ -> 42) (Validator (\x -> if x > 0 then Success x else Failure ["not positive"]) :: Validator Int [String] Int)
+>>> f 5
+Success 42
+
+>>> f (-1)
+Failure ["not positive"]
 -}
 instance Extend (Validator x err) where
-  extended f w@(Validator _) = Validator (\_ -> Success (f w))
+  extended f w@(Validator g) = Validator (\x -> f w <$ g x)
   {-# INLINE extended #-}
 
-{- |
+{- | First success wins; two failures accumulate. Unlike '<!>' for 'Validator',
+this requires 'Semigroup' on @err@.
+
 >>> let Validator f = (Validator (\_ -> Failure ["e1"]) :: Validator Int [String] Int) <> Validator (\_ -> Failure ["e2"])
 >>> f 0
 Failure ["e1","e2"]
@@ -358,7 +380,7 @@
   reviewValidator :: Review s (Validator x err a)
 
 instance ReviewValidator (Validator x err a) x err a where
-  reviewValidator = unto id
+  reviewValidator = id
   {-# INLINE reviewValidator #-}
 
 -- | Class for types that have a 'Prism'' to a 'Validator'.
@@ -540,10 +562,10 @@
 >>> runVP (right' vpFromInput) (Left "x" :: Either String Int)
 Success (Left "x")
 -}
-instance (Semigroup err) => Choice (ValidatorProfunctor err) where
-  left' (ValidatorProfunctor f) = ValidatorProfunctor (either (fmap Left . f) (pure . Right))
+instance Choice (ValidatorProfunctor err) where
+  left' (ValidatorProfunctor f) = ValidatorProfunctor (either (fmap Left . f) (Success . Right))
   {-# INLINE left' #-}
-  right' (ValidatorProfunctor f) = ValidatorProfunctor (either (pure . Left) (fmap Right . f))
+  right' (ValidatorProfunctor f) = ValidatorProfunctor (either (Success . Left) (fmap Right . f))
   {-# INLINE right' #-}
 
 {- |
@@ -567,12 +589,17 @@
   sieve (ValidatorProfunctor f) = f
   {-# INLINE sieve #-}
 
-{- |
+{- | Like 'Validation', a failure is kept: for each input, the result fails
+where the validator fails, and otherwise succeeds with @f@ applied to the validator.
+
 >>> runVP (extended (\_ -> 42) vpFromInput) 0
 Success 42
+
+>>> runVP (extended (\_ -> 42) (vpErr ["e"])) 0
+Failure ["e"]
 -}
 instance Extend (ValidatorProfunctor err x) where
-  extended f w@(ValidatorProfunctor _) = ValidatorProfunctor (\_ -> Success (f w))
+  extended f w@(ValidatorProfunctor g) = ValidatorProfunctor (\x -> f w <$ g x)
   {-# INLINE extended #-}
 
 {- |
@@ -627,7 +654,7 @@
   reviewValidatorProfunctor :: Review s (ValidatorProfunctor err x a)
 
 instance ReviewValidatorProfunctor (ValidatorProfunctor err x a) err x a where
-  reviewValidatorProfunctor = unto id
+  reviewValidatorProfunctor = id
   {-# INLINE reviewValidatorProfunctor #-}
 
 {- |
@@ -750,7 +777,7 @@
   ValidatorMonadT f >>= k = ValidatorMonadT (\x -> f x >>= \a -> let ValidatorMonadT g = k a in g x)
   {-# INLINE (>>=) #-}
 
-instance (Monad f, MonadFail f) => MonadFail (ValidatorMonadT x err f) where
+instance (MonadFail f) => MonadFail (ValidatorMonadT x err f) where
   fail = ValidatorMonadT . const . liftValidationMonadT . Prelude.fail
   {-# INLINE fail #-}
 
@@ -812,7 +839,10 @@
   select = selectM
   {-# INLINE select #-}
 
-{- |
+{- | Like 'Validation', a failure is kept: for each input, the result fails
+where the validator fails, and otherwise succeeds with @f@ applied to the validator.
+The effects of the validator are run.
+
 >>> import Data.Functor.Identity (Identity(..))
 >>> import Data.Validation.Validation (Validation(..))
 >>> import Data.Validation.ValidationMonad (ValidationMonadT(..))
@@ -820,9 +850,13 @@
 >>> let v = ValidatorMonadT (\_ -> ValidationMonadT (Identity (Success 1))) :: ValidatorMonadT Int [String] Identity Int
 >>> let ValidatorMonadT f = extended (\_ -> 42) v in let ValidationMonadT (Identity r) = f 0 in r
 Success 42
+
+>>> let e = ValidatorMonadT (\_ -> ValidationMonadT (Identity (Failure ["e"]))) :: ValidatorMonadT Int [String] Identity Int
+>>> let ValidatorMonadT f = extended (\_ -> 42) e in let ValidationMonadT (Identity r) = f 0 in r
+Failure ["e"]
 -}
-instance (Monad f) => Extend (ValidatorMonadT x err f) where
-  extended f w@(ValidatorMonadT _) = ValidatorMonadT (\_ -> pure (f w))
+instance (Functor f) => Extend (ValidatorMonadT x err f) where
+  extended f w@(ValidatorMonadT g) = ValidatorMonadT (\x -> f w <$ g x)
   {-# INLINE extended #-}
 
 {- |
@@ -955,7 +989,7 @@
   reviewValidatorMonadT :: Review s (ValidatorMonadT x err f a)
 
 instance ReviewValidatorMonadT (ValidatorMonadT x err f a) x err f a where
-  reviewValidatorMonadT = unto id
+  reviewValidatorMonadT = id
   {-# INLINE reviewValidatorMonadT #-}
 
 class (ReviewValidatorMonadT s x err f a) => AsValidatorMonadT s x err f a | s -> x err f a where
@@ -1192,7 +1226,7 @@
 >>> r
 Success 4
 -}
-instance (Monad f) => Sieve (ValidatorMonadProfunctorT err f) (ValidationMonadT err f) where
+instance (Functor f) => Sieve (ValidatorMonadProfunctorT err f) (ValidationMonadT err f) where
   sieve (ValidatorMonadProfunctorT f) = f
   {-# INLINE sieve #-}
 
@@ -1300,16 +1334,24 @@
   ValidatorMonadProfunctorT f <+> ValidatorMonadProfunctorT g = ValidatorMonadProfunctorT (\x -> f x <!> g x)
   {-# INLINE (<+>) #-}
 
-{- |
+{- | Like 'Validation', a failure is kept: for each input, the result fails
+where the validator fails, and otherwise succeeds with @f@ applied to the validator.
+The effects of the validator are run.
+
 >>> import Control.Lens(view, _Wrapped')
 >>> import Data.Functor.Extend(Extend(extended))
 >>> let v = ValidatorMonadProfunctorT (\x -> ValidationMonadT (Identity (Success (x + 1)))) :: ValidatorMonadProfunctorT [String] Identity Int Int
 >>> let ValidationMonadT (Identity r) = view _Wrapped' (extended (\_ -> 99) v) 3
 >>> r
 Success 99
+
+>>> let e = ValidatorMonadProfunctorT (\_ -> ValidationMonadT (Identity (Failure ["e"]))) :: ValidatorMonadProfunctorT [String] Identity Int Int
+>>> let ValidationMonadT (Identity r) = view _Wrapped' (extended (\_ -> 99) e) 3
+>>> r
+Failure ["e"]
 -}
-instance (Monad f) => Extend (ValidatorMonadProfunctorT err f x) where
-  extended f w@(ValidatorMonadProfunctorT _) = ValidatorMonadProfunctorT (\_ -> pure (f w))
+instance (Functor f) => Extend (ValidatorMonadProfunctorT err f x) where
+  extended f w@(ValidatorMonadProfunctorT g) = ValidatorMonadProfunctorT (\x -> f w <$ g x)
   {-# INLINE extended #-}
 
 {- |
@@ -1334,7 +1376,7 @@
   mempty = ValidatorMonadProfunctorT (const mempty)
   {-# INLINE mempty #-}
 
-instance (Monad f, MonadFail f) => MonadFail (ValidatorMonadProfunctorT err f x) where
+instance (MonadFail f) => MonadFail (ValidatorMonadProfunctorT err f x) where
   fail = ValidatorMonadProfunctorT . const . liftValidationMonadT . Prelude.fail
   {-# INLINE fail #-}
 
@@ -1414,7 +1456,7 @@
   reviewValidatorMonadProfunctorT :: Review s (ValidatorMonadProfunctorT err f x a)
 
 instance ReviewValidatorMonadProfunctorT (ValidatorMonadProfunctorT err f x a) err f x a where
-  reviewValidatorMonadProfunctorT = unto id
+  reviewValidatorMonadProfunctorT = id
   {-# INLINE reviewValidatorMonadProfunctorT #-}
 
 -- | Class for types that have a 'Prism'' to a 'ValidatorMonadProfunctorT'.
@@ -1429,82 +1471,108 @@
 -- Cross-type optics instances
 -- =============================
 
+-- Isomorphisms between the validator types, used by the cross-type instances.
+
+validatorToProfunctor :: Iso' (Validator x err a) (ValidatorProfunctor err x a)
+validatorToProfunctor = iso (\(Validator f) -> ValidatorProfunctor f) (\(ValidatorProfunctor f) -> Validator f)
+{-# INLINE validatorToProfunctor #-}
+
+monadToMonadProfunctor :: Iso' (ValidatorMonadT x err f a) (ValidatorMonadProfunctorT err f x a)
+monadToMonadProfunctor = iso (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f) (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f)
+{-# INLINE monadToMonadProfunctor #-}
+
+validatorToMonad :: Iso' (Validator x err a) (ValidatorMonad x err a)
+validatorToMonad = iso (\(Validator f) -> ValidatorMonadT (view validationMonad . f)) (\(ValidatorMonadT f) -> Validator (review validationMonad . f))
+{-# INLINE validatorToMonad #-}
+
+validatorToMonadProfunctor :: Iso' (Validator x err a) (ValidatorMonadProfunctor err x a)
+validatorToMonadProfunctor = validatorToMonad . monadToMonadProfunctor
+{-# INLINE validatorToMonadProfunctor #-}
+
+profunctorToMonad :: Iso' (ValidatorProfunctor err x a) (ValidatorMonad x err a)
+profunctorToMonad = from validatorToProfunctor . validatorToMonad
+{-# INLINE profunctorToMonad #-}
+
+profunctorToMonadProfunctor :: Iso' (ValidatorProfunctor err x a) (ValidatorMonadProfunctor err x a)
+profunctorToMonadProfunctor = from validatorToProfunctor . validatorToMonadProfunctor
+{-# INLINE profunctorToMonadProfunctor #-}
+
 -- Cross-type optics: Validator <-> ValidatorProfunctor
 
 instance GetValidator (ValidatorProfunctor err x a) x err a where
-  getValidator = iso (\(ValidatorProfunctor f) -> Validator f) (\(Validator f) -> ValidatorProfunctor f)
+  getValidator = from validatorToProfunctor
   {-# INLINE getValidator #-}
 
 instance HasValidator (ValidatorProfunctor err x a) x err a where
-  validator = iso (\(ValidatorProfunctor f) -> Validator f) (\(Validator f) -> ValidatorProfunctor f)
+  validator = from validatorToProfunctor
   {-# INLINE validator #-}
 
 instance ReviewValidator (ValidatorProfunctor err x a) x err a where
-  reviewValidator = unto (\(Validator f) -> ValidatorProfunctor f)
+  reviewValidator = from validatorToProfunctor
   {-# INLINE reviewValidator #-}
 
 instance AsValidator (ValidatorProfunctor err x a) x err a where
-  _Validator = iso (\(ValidatorProfunctor f) -> Validator f) (\(Validator f) -> ValidatorProfunctor f)
+  _Validator = from validatorToProfunctor
   {-# INLINE _Validator #-}
 
 instance GetValidatorProfunctor (Validator x err a) err x a where
-  getValidatorProfunctor = iso (\(Validator f) -> ValidatorProfunctor f) (\(ValidatorProfunctor f) -> Validator f)
+  getValidatorProfunctor = validatorToProfunctor
   {-# INLINE getValidatorProfunctor #-}
 
 instance HasValidatorProfunctor (Validator x err a) err x a where
-  validatorProfunctor = iso (\(Validator f) -> ValidatorProfunctor f) (\(ValidatorProfunctor f) -> Validator f)
+  validatorProfunctor = validatorToProfunctor
   {-# INLINE validatorProfunctor #-}
 
 instance ReviewValidatorProfunctor (Validator x err a) err x a where
-  reviewValidatorProfunctor = unto (\(ValidatorProfunctor f) -> Validator f)
+  reviewValidatorProfunctor = validatorToProfunctor
   {-# INLINE reviewValidatorProfunctor #-}
 
 instance AsValidatorProfunctor (Validator x err a) err x a where
-  _ValidatorProfunctor = iso (\(Validator f) -> ValidatorProfunctor f) (\(ValidatorProfunctor f) -> Validator f)
+  _ValidatorProfunctor = validatorToProfunctor
   {-# INLINE _ValidatorProfunctor #-}
 
 -- Cross-type optics: ValidatorMonadT <-> ValidatorMonadProfunctorT
 
 instance GetValidatorMonadT (ValidatorMonadProfunctorT err f x a) x err f a where
-  getValidatorMonadT = iso (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f) (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f)
+  getValidatorMonadT = from monadToMonadProfunctor
   {-# INLINE getValidatorMonadT #-}
 
 instance HasValidatorMonadT (ValidatorMonadProfunctorT err f x a) x err f a where
-  validatorMonadT = iso (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f) (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f)
+  validatorMonadT = from monadToMonadProfunctor
   {-# INLINE validatorMonadT #-}
 
 instance ReviewValidatorMonadT (ValidatorMonadProfunctorT err f x a) x err f a where
-  reviewValidatorMonadT = unto (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f)
+  reviewValidatorMonadT = from monadToMonadProfunctor
   {-# INLINE reviewValidatorMonadT #-}
 
 instance AsValidatorMonadT (ValidatorMonadProfunctorT err f x a) x err f a where
-  _ValidatorMonadT = iso (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f) (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f)
+  _ValidatorMonadT = from monadToMonadProfunctor
   {-# INLINE _ValidatorMonadT #-}
 
 instance GetValidatorMonadProfunctorT (ValidatorMonadT x err f a) err f x a where
-  getValidatorMonadProfunctorT = iso (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f) (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f)
+  getValidatorMonadProfunctorT = monadToMonadProfunctor
   {-# INLINE getValidatorMonadProfunctorT #-}
 
 instance HasValidatorMonadProfunctorT (ValidatorMonadT x err f a) err f x a where
-  validatorMonadProfunctorT = iso (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f) (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f)
+  validatorMonadProfunctorT = monadToMonadProfunctor
   {-# INLINE validatorMonadProfunctorT #-}
 
 instance ReviewValidatorMonadProfunctorT (ValidatorMonadT x err f a) err f x a where
-  reviewValidatorMonadProfunctorT = unto (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f)
+  reviewValidatorMonadProfunctorT = monadToMonadProfunctor
   {-# INLINE reviewValidatorMonadProfunctorT #-}
 
 instance AsValidatorMonadProfunctorT (ValidatorMonadT x err f a) err f x a where
-  _ValidatorMonadProfunctorT = iso (\(ValidatorMonadT f) -> ValidatorMonadProfunctorT f) (\(ValidatorMonadProfunctorT f) -> ValidatorMonadT f)
+  _ValidatorMonadProfunctorT = monadToMonadProfunctor
   {-# INLINE _ValidatorMonadProfunctorT #-}
 
 -- Cross-type optics: Validator <-> ValidatorMonadT (f ~ Identity)
 
 instance GetValidator (ValidatorMonadT x err Identity a) x err a where
-  getValidator = iso (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  getValidator = from validatorToMonad
   {-# INLINE getValidator #-}
 
 instance HasValidator (ValidatorMonadT x err Identity a) x err a where
-  validator = iso (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  validator = from validatorToMonad
   {-# INLINE validator #-}
 
 instance (Applicative f) => ReviewValidator (ValidatorMonadT x err f a) x err a where
@@ -1512,33 +1580,33 @@
   {-# INLINE reviewValidator #-}
 
 instance AsValidator (ValidatorMonadT x err Identity a) x err a where
-  _Validator = iso (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  _Validator = from validatorToMonad
   {-# INLINE _Validator #-}
 
 instance GetValidatorMonadT (Validator x err a) x err Identity a where
-  getValidatorMonadT = iso (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  getValidatorMonadT = validatorToMonad
   {-# INLINE getValidatorMonadT #-}
 
 instance HasValidatorMonadT (Validator x err a) x err Identity a where
-  validatorMonadT = iso (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  validatorMonadT = validatorToMonad
   {-# INLINE validatorMonadT #-}
 
 instance ReviewValidatorMonadT (Validator x err a) x err Identity a where
-  reviewValidatorMonadT = unto (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  reviewValidatorMonadT = validatorToMonad
   {-# INLINE reviewValidatorMonadT #-}
 
 instance AsValidatorMonadT (Validator x err a) x err Identity a where
-  _ValidatorMonadT = iso (\(Validator f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  _ValidatorMonadT = validatorToMonad
   {-# INLINE _ValidatorMonadT #-}
 
 -- Cross-type optics: ValidatorProfunctor <-> ValidatorMonadProfunctorT (f ~ Identity)
 
 instance GetValidatorProfunctor (ValidatorMonadProfunctorT err Identity x a) err x a where
-  getValidatorProfunctor = iso (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  getValidatorProfunctor = from profunctorToMonadProfunctor
   {-# INLINE getValidatorProfunctor #-}
 
 instance HasValidatorProfunctor (ValidatorMonadProfunctorT err Identity x a) err x a where
-  validatorProfunctor = iso (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  validatorProfunctor = from profunctorToMonadProfunctor
   {-# INLINE validatorProfunctor #-}
 
 instance (Applicative f) => ReviewValidatorProfunctor (ValidatorMonadProfunctorT err f x a) err x a where
@@ -1546,33 +1614,33 @@
   {-# INLINE reviewValidatorProfunctor #-}
 
 instance AsValidatorProfunctor (ValidatorMonadProfunctorT err Identity x a) err x a where
-  _ValidatorProfunctor = iso (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  _ValidatorProfunctor = from profunctorToMonadProfunctor
   {-# INLINE _ValidatorProfunctor #-}
 
 instance GetValidatorMonadProfunctorT (ValidatorProfunctor err x a) err Identity x a where
-  getValidatorMonadProfunctorT = iso (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  getValidatorMonadProfunctorT = profunctorToMonadProfunctor
   {-# INLINE getValidatorMonadProfunctorT #-}
 
 instance HasValidatorMonadProfunctorT (ValidatorProfunctor err x a) err Identity x a where
-  validatorMonadProfunctorT = iso (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  validatorMonadProfunctorT = profunctorToMonadProfunctor
   {-# INLINE validatorMonadProfunctorT #-}
 
 instance ReviewValidatorMonadProfunctorT (ValidatorProfunctor err x a) err Identity x a where
-  reviewValidatorMonadProfunctorT = unto (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  reviewValidatorMonadProfunctorT = profunctorToMonadProfunctor
   {-# INLINE reviewValidatorMonadProfunctorT #-}
 
 instance AsValidatorMonadProfunctorT (ValidatorProfunctor err x a) err Identity x a where
-  _ValidatorMonadProfunctorT = iso (\(ValidatorProfunctor f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  _ValidatorMonadProfunctorT = profunctorToMonadProfunctor
   {-# INLINE _ValidatorMonadProfunctorT #-}
 
 -- Cross-type optics: Validator <-> ValidatorMonadProfunctorT (f ~ Identity)
 
 instance GetValidator (ValidatorMonadProfunctorT err Identity x a) x err a where
-  getValidator = iso (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  getValidator = from validatorToMonadProfunctor
   {-# INLINE getValidator #-}
 
 instance HasValidator (ValidatorMonadProfunctorT err Identity x a) x err a where
-  validator = iso (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  validator = from validatorToMonadProfunctor
   {-# INLINE validator #-}
 
 instance (Applicative f) => ReviewValidator (ValidatorMonadProfunctorT err f x a) x err a where
@@ -1580,33 +1648,33 @@
   {-# INLINE reviewValidator #-}
 
 instance AsValidator (ValidatorMonadProfunctorT err Identity x a) x err a where
-  _Validator = iso (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f))
+  _Validator = from validatorToMonadProfunctor
   {-# INLINE _Validator #-}
 
 instance GetValidatorMonadProfunctorT (Validator x err a) err Identity x a where
-  getValidatorMonadProfunctorT = iso (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  getValidatorMonadProfunctorT = validatorToMonadProfunctor
   {-# INLINE getValidatorMonadProfunctorT #-}
 
 instance HasValidatorMonadProfunctorT (Validator x err a) err Identity x a where
-  validatorMonadProfunctorT = iso (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  validatorMonadProfunctorT = validatorToMonadProfunctor
   {-# INLINE validatorMonadProfunctorT #-}
 
 instance ReviewValidatorMonadProfunctorT (Validator x err a) err Identity x a where
-  reviewValidatorMonadProfunctorT = unto (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  reviewValidatorMonadProfunctorT = validatorToMonadProfunctor
   {-# INLINE reviewValidatorMonadProfunctorT #-}
 
 instance AsValidatorMonadProfunctorT (Validator x err a) err Identity x a where
-  _ValidatorMonadProfunctorT = iso (\(Validator f) -> ValidatorMonadProfunctorT (ValidationMonadT . Identity . f)) (\(ValidatorMonadProfunctorT f) -> Validator (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  _ValidatorMonadProfunctorT = validatorToMonadProfunctor
   {-# INLINE _ValidatorMonadProfunctorT #-}
 
 -- Cross-type optics: ValidatorProfunctor <-> ValidatorMonadT (f ~ Identity)
 
 instance GetValidatorProfunctor (ValidatorMonadT x err Identity a) err x a where
-  getValidatorProfunctor = iso (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  getValidatorProfunctor = from profunctorToMonad
   {-# INLINE getValidatorProfunctor #-}
 
 instance HasValidatorProfunctor (ValidatorMonadT x err Identity a) err x a where
-  validatorProfunctor = iso (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  validatorProfunctor = from profunctorToMonad
   {-# INLINE validatorProfunctor #-}
 
 instance (Applicative f) => ReviewValidatorProfunctor (ValidatorMonadT x err f a) err x a where
@@ -1614,23 +1682,23 @@
   {-# INLINE reviewValidatorProfunctor #-}
 
 instance AsValidatorProfunctor (ValidatorMonadT x err Identity a) err x a where
-  _ValidatorProfunctor = iso (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f)) (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f))
+  _ValidatorProfunctor = from profunctorToMonad
   {-# INLINE _ValidatorProfunctor #-}
 
 instance GetValidatorMonadT (ValidatorProfunctor err x a) x err Identity a where
-  getValidatorMonadT = iso (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  getValidatorMonadT = profunctorToMonad
   {-# INLINE getValidatorMonadT #-}
 
 instance HasValidatorMonadT (ValidatorProfunctor err x a) x err Identity a where
-  validatorMonadT = iso (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  validatorMonadT = profunctorToMonad
   {-# INLINE validatorMonadT #-}
 
 instance ReviewValidatorMonadT (ValidatorProfunctor err x a) x err Identity a where
-  reviewValidatorMonadT = unto (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  reviewValidatorMonadT = profunctorToMonad
   {-# INLINE reviewValidatorMonadT #-}
 
 instance AsValidatorMonadT (ValidatorProfunctor err x a) x err Identity a where
-  _ValidatorMonadT = iso (\(ValidatorProfunctor f) -> ValidatorMonadT (ValidationMonadT . Identity . f)) (\(ValidatorMonadT f) -> ValidatorProfunctor (runIdentity . (\(ValidationMonadT m) -> m) . f))
+  _ValidatorMonadT = profunctorToMonad
   {-# INLINE _ValidatorMonadT #-}
 
 -- ==================================
diff --git a/validation.cabal b/validation.cabal
--- a/validation.cabal
+++ b/validation.cabal
@@ -1,5 +1,5 @@
 name:               validation
-version:            1.3.1
+version:            1.3.2
 license:            BSD3
 license-file:       LICENCE
 author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> <dibblego>, Nick Partridge <nkpart>
@@ -45,12 +45,18 @@
   Four validator newtypes wrap a validation function with different type
   parameter orders, enabling different class instances:
   .
-  * @Validator x err a@ — @Bifunctor@, accumulating @Applicative@
+  * @Validator x err a@ — @Bifunctor@, accumulating @Applicative@, @Either@-like @Alt@
   * @ValidatorProfunctor err x a@ — @Profunctor@, accumulating @Applicative@
   * @ValidatorMonadT x err f a@ — @Monad@, @MonadTrans@, @BindTrans@
   * @ValidatorMonadProfunctorT err f x a@ — @Profunctor@, @Monad@, @Category@, @Arrow@
   .
   All four are isomorphic and have cross-type optics instances.
+  .
+  @Validator@ is the odd one out in its @Alt@ instance. For the other three
+  validators, @\<!\>@ accumulates errors when both sides fail. For @Validator@,
+  @\<!\>@ behaves like @Either@: the first success wins, otherwise the second
+  failure is returned. @Validator@ has no @Plus@ or @Alternative@ instance, and
+  its @\<\>@ still accumulates errors.
 
 homepage:           https://github.com/system-f/validation
 bug-reports:        https://github.com/system-f/validation/issues
